<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rahul Singh</title>
    <description>The latest articles on DEV Community by Rahul Singh (@rahulxsingh).</description>
    <link>https://dev.to/rahulxsingh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3821051%2Fc871b6c4-e4ab-4dc7-87d4-015d6d227d34.png</url>
      <title>DEV Community: Rahul Singh</title>
      <link>https://dev.to/rahulxsingh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rahulxsingh"/>
    <language>en</language>
    <item>
      <title>SWE-bench Scores and Leaderboard Explained (2026)</title>
      <dc:creator>Rahul Singh</dc:creator>
      <pubDate>Sat, 11 Apr 2026 20:00:00 +0000</pubDate>
      <link>https://dev.to/rahulxsingh/swe-bench-scores-and-leaderboard-explained-2026-54of</link>
      <guid>https://dev.to/rahulxsingh/swe-bench-scores-and-leaderboard-explained-2026-54of</guid>
      <description>&lt;p&gt;If you follow AI coding tools, you have probably seen companies quoting their SWE-bench scores in every product announcement and marketing page. But what do these numbers actually mean? And more importantly, should you pick your AI coding tools based on benchmark scores alone?&lt;/p&gt;

&lt;p&gt;SWE-bench has become the de facto standard for measuring how well AI models can solve real software engineering problems. In this guide, I will break down how the benchmark works, walk through the current leaderboard, explain what the scores actually tell you (and what they don't), and help you make sense of the numbers when choosing tools for your workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is SWE-bench?
&lt;/h2&gt;

&lt;p&gt;SWE-bench (Software Engineering Benchmark) is a benchmark created by researchers at Princeton University to evaluate whether large language models can resolve real-world GitHub issues. Unlike synthetic coding benchmarks that test isolated functions or algorithm puzzles, SWE-bench uses actual bug reports and feature requests pulled from popular open-source Python repositories.&lt;/p&gt;

&lt;p&gt;The original dataset contains 2,294 task instances drawn from 12 popular Python projects including Django, Flask, scikit-learn, matplotlib, sympy, and others. Each task corresponds to a real pull request that was merged to fix an issue.&lt;/p&gt;

&lt;h3&gt;
  
  
  How the Evaluation Works
&lt;/h3&gt;

&lt;p&gt;The evaluation process follows a straightforward but rigorous methodology:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The model receives&lt;/strong&gt; a GitHub issue description and access to the full codebase at the point in time when the issue was filed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The model must generate&lt;/strong&gt; a patch (a code diff) that resolves the described problem&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The patch is tested&lt;/strong&gt; by running the repository's unit test suite - specifically, tests that were added alongside the original fix&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Success is binary&lt;/strong&gt; - the model's patch must make previously failing tests pass without breaking any existing tests&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each task runs inside an isolated Docker container to ensure reproducibility. The model does not see the test cases it needs to pass - it only gets the issue description and the repository code.&lt;/p&gt;

&lt;p&gt;This "fail-to-pass" methodology is what makes SWE-bench harder than most coding benchmarks. The model needs to understand the bug from a natural language description, locate the relevant code in a potentially massive codebase, and produce a working fix - all without seeing the expected test outcomes.&lt;/p&gt;

&lt;h2&gt;
  
  
  SWE-bench Verified vs. SWE-bench Pro
&lt;/h2&gt;

&lt;p&gt;The original SWE-bench dataset had a known problem: some tasks were ambiguous, poorly specified, or arguably unsolvable from the issue description alone. This made it hard to tell whether a model failed because it lacked capability or because the task itself was unfair.&lt;/p&gt;

&lt;h3&gt;
  
  
  SWE-bench Verified
&lt;/h3&gt;

&lt;p&gt;OpenAI collaborated with the SWE-bench team to create SWE-bench Verified - a curated subset of 500 tasks that were individually reviewed by software engineers. Each annotator confirmed that the issue description contained enough information to solve the problem and that the test patch was a valid evaluation of the fix.&lt;/p&gt;

&lt;p&gt;SWE-bench Verified quickly became the primary benchmark everyone reported scores on. However, it has since run into a serious problem: &lt;strong&gt;data contamination&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;OpenAI's audit found that every frontier model tested - including GPT-5.2, Claude Opus 4.5, and Gemini 3 Flash - could reproduce verbatim gold patches or problem statement specifics for certain SWE-bench Verified tasks. In other words, the models have likely seen the answers during training. This means the 80%+ scores on Verified may be inflated.&lt;/p&gt;

&lt;h3&gt;
  
  
  SWE-bench Pro
&lt;/h3&gt;

&lt;p&gt;In response to contamination concerns, Scale AI launched SWE-bench Pro - a harder benchmark with 1,865 multi-language tasks that avoids the data contamination issues. The results are dramatically different: models that score 80%+ on Verified only reach about 46-57% on Pro.&lt;/p&gt;

&lt;p&gt;This gap is telling. A model scoring 46% on Pro versus 81% on Verified does not mean it got worse - it means Pro is a more honest measurement of current capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Current SWE-bench Leaderboard (March 2026)
&lt;/h2&gt;

&lt;p&gt;Here are the latest scores across both benchmarks as of March 2026.&lt;/p&gt;

&lt;h3&gt;
  
  
  SWE-bench Verified Top 10
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rank&lt;/th&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Claude Opus 4.5&lt;/td&gt;
&lt;td&gt;80.9%&lt;/td&gt;
&lt;td&gt;Anthropic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Claude Opus 4.6&lt;/td&gt;
&lt;td&gt;80.8%&lt;/td&gt;
&lt;td&gt;Anthropic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Gemini 3.1 Pro&lt;/td&gt;
&lt;td&gt;80.6%&lt;/td&gt;
&lt;td&gt;Google&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;MiniMax M2.5&lt;/td&gt;
&lt;td&gt;80.2%&lt;/td&gt;
&lt;td&gt;MiniMax&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;GPT-5.2&lt;/td&gt;
&lt;td&gt;80.0%&lt;/td&gt;
&lt;td&gt;OpenAI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Claude Sonnet 4.6&lt;/td&gt;
&lt;td&gt;79.6%&lt;/td&gt;
&lt;td&gt;Anthropic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;GLM-5&lt;/td&gt;
&lt;td&gt;~79%&lt;/td&gt;
&lt;td&gt;Zhipu AI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Kimi K2.5&lt;/td&gt;
&lt;td&gt;~79%&lt;/td&gt;
&lt;td&gt;Moonshot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;DeepSeek V3.2&lt;/td&gt;
&lt;td&gt;~78%&lt;/td&gt;
&lt;td&gt;DeepSeek&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Gemini 3 Flash&lt;/td&gt;
&lt;td&gt;~78%&lt;/td&gt;
&lt;td&gt;Google&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Average across all 77 ranked models: 62.2%&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The top of SWE-bench Verified is extremely tight. Six models sit within 1.3 percentage points of each other. The practical difference between the top-ranked and fifth-ranked model is less than one percentage point - which is well within the margin of noise introduced by scaffolding differences and contamination.&lt;/p&gt;

&lt;h3&gt;
  
  
  SWE-bench Pro Top Scores
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rank&lt;/th&gt;
&lt;th&gt;Model / System&lt;/th&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;GPT-5.3-Codex&lt;/td&gt;
&lt;td&gt;56.8%&lt;/td&gt;
&lt;td&gt;OpenAI's agent-optimized model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;GPT-5.2-Codex&lt;/td&gt;
&lt;td&gt;56.4%&lt;/td&gt;
&lt;td&gt;Previous Codex generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;GPT-5.2&lt;/td&gt;
&lt;td&gt;55.6%&lt;/td&gt;
&lt;td&gt;Base model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Claude Opus 4.5 (SEAL)&lt;/td&gt;
&lt;td&gt;45.9%&lt;/td&gt;
&lt;td&gt;Scale AI standardized scaffolding&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;SWE-bench Pro tells a different story. OpenAI's Codex line dominates here, and the overall scores are dramatically lower. Note that these scores are harder to compare directly because different submissions use different scaffolding (the tooling and prompting surrounding the model).&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Scores Actually Mean
&lt;/h2&gt;

&lt;p&gt;Let's put these numbers in practical context.&lt;/p&gt;

&lt;h3&gt;
  
  
  An 80% on Verified Sounds Impressive - But Context Matters
&lt;/h3&gt;

&lt;p&gt;An 80% score means the model can generate a correct patch for 400 out of 500 curated bug fixes. That is genuinely impressive. But there are important caveats:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The tasks are well-defined.&lt;/strong&gt; Each issue has a clear description and a known, specific fix. Real-world bugs are rarely this cleanly specified. Developers spend significant time just understanding what the problem is before writing a single line of code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The model works on one file or a few files.&lt;/strong&gt; Most SWE-bench fixes involve changes to a small number of files. The model does not need to architect a new system, refactor across dozens of modules, or make design tradeoffs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The evaluation is binary.&lt;/strong&gt; Either the tests pass or they don't. There is no evaluation of code quality, readability, performance, or whether the fix introduces subtle regressions the test suite does not cover.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contamination inflates scores.&lt;/strong&gt; With confirmed data contamination across all frontier models on Verified, some portion of that 80% represents memorization rather than genuine problem-solving ability.&lt;/p&gt;

&lt;h3&gt;
  
  
  A 57% on Pro Is More Honest
&lt;/h3&gt;

&lt;p&gt;SWE-bench Pro scores are lower but more trustworthy. A 57% means the model can solve about 1,060 out of 1,865 harder, multi-language tasks without having seen the answers. This is still remarkable - it means these models can genuinely fix a majority of well-specified bugs across Python, JavaScript, TypeScript, Java, and Go repositories.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the Scores Do Not Measure
&lt;/h3&gt;

&lt;p&gt;SWE-bench does not test several capabilities that matter enormously in professional software engineering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Architecture and design&lt;/strong&gt; - choosing the right abstractions, patterns, and system boundaries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Requirements analysis&lt;/strong&gt; - figuring out what to build when the specification is vague or contradictory&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code review quality&lt;/strong&gt; - evaluating someone else's code for style, security, performance, and maintainability&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaboration&lt;/strong&gt; - communicating technical decisions, writing documentation, and mentoring&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long-running projects&lt;/strong&gt; - maintaining context across weeks of work on a complex feature&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Novel problem solving&lt;/strong&gt; - creating solutions to problems that have no precedent in training data&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Scaffolding Problem
&lt;/h2&gt;

&lt;p&gt;One of the most underappreciated aspects of SWE-bench scores is how much the &lt;strong&gt;scaffolding&lt;/strong&gt; matters. Scaffolding refers to everything around the model - the prompt engineering, the tools the model can use, the search and retrieval system, the iterative feedback loop, and the overall agent architecture.&lt;/p&gt;

&lt;p&gt;The same underlying model can produce wildly different SWE-bench scores depending on the scaffolding. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A bare model with a simple prompt might score 30%&lt;/li&gt;
&lt;li&gt;The same model with a well-designed agent framework like SWE-Agent or OpenHands might score 60%+&lt;/li&gt;
&lt;li&gt;The same model with a heavily optimized, proprietary scaffolding might score 80%+&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why comparing raw SWE-bench numbers between different submissions is tricky. When Anthropic reports a score for Claude Opus 4.5, they are reporting the best result with their chosen scaffolding. When Scale AI reports a score on their SEAL leaderboard, they use standardized scaffolding that may disadvantage models optimized for different tool-use patterns.&lt;/p&gt;

&lt;p&gt;The practical takeaway: &lt;strong&gt;the agent framework matters as much as the model.&lt;/strong&gt; A great model with mediocre scaffolding will underperform a good model with excellent scaffolding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key AI Coding Agents and Their SWE-bench Results
&lt;/h2&gt;

&lt;p&gt;Beyond raw model scores, several complete agent systems have been evaluated on SWE-bench.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenAI Codex
&lt;/h3&gt;

&lt;p&gt;OpenAI's Codex is purpose-built for autonomous coding tasks. The GPT-5.3-Codex variant leads SWE-bench Pro at 56.8%, demonstrating that specializing a model for agentic coding workflows produces measurably better results than using a general-purpose model. Codex benefits from tight integration with OpenAI's tool-use infrastructure and optimized scaffolding for code search and editing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Claude Code
&lt;/h3&gt;

&lt;p&gt;Anthropic's Claude Code uses Claude Opus 4.6 (the model behind the 80.8% Verified score) as its backbone. While Anthropic has not published official Claude Code agent scores on SWE-bench Pro with standardized scaffolding, Claude Sonnet 4.6 at 79.6% on Verified shows that even Anthropic's mid-tier model nearly matches flagship competitors - making it a strong choice for cost-sensitive workflows at $3/$15 per million tokens.&lt;/p&gt;

&lt;h3&gt;
  
  
  Devin
&lt;/h3&gt;

&lt;p&gt;Cognition's Devin was one of the first AI agents to gain attention for SWE-bench performance. Devin uses a full autonomous development environment with a browser, terminal, and code editor. While early Devin scores were groundbreaking at the time, the rapid improvement of foundation models means most frontier models now exceed Devin's original SWE-bench scores when paired with good scaffolding.&lt;/p&gt;

&lt;h3&gt;
  
  
  SWE-Agent and OpenHands
&lt;/h3&gt;

&lt;p&gt;These open-source agent frameworks demonstrate how scaffolding design impacts results. SWE-Agent, developed by the Princeton team behind SWE-bench itself, pioneered many of the agent patterns now used by commercial products. OpenHands (formerly OpenDevin) provides an open-source alternative with its CodeAct architecture. Both frameworks allow you to swap in different underlying models, making them useful for fair model-to-model comparisons.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations of SWE-bench as a Benchmark
&lt;/h2&gt;

&lt;p&gt;While SWE-bench is far more realistic than traditional coding benchmarks, it has several well-documented limitations:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Data Contamination
&lt;/h3&gt;

&lt;p&gt;This is the elephant in the room. Every frontier model has been found to exhibit signs of training data contamination on SWE-bench Verified. Models can sometimes reproduce exact patch text from the training data rather than reasoning about the problem from scratch. SWE-bench Pro was created to address this, but contamination will remain a persistent challenge as models train on increasingly large portions of the public internet.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Task Ambiguity
&lt;/h3&gt;

&lt;p&gt;Even after the Verified curation, some tasks contain issue descriptions that are genuinely ambiguous. The model must guess the exact fix the maintainers chose, including specific variable names, error messages, and implementation details that could reasonably go multiple ways. This means SWE-bench systematically underestimates capability in some cases - the model may produce a valid fix that happens to differ from the gold patch.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Python-Heavy (for Verified)
&lt;/h3&gt;

&lt;p&gt;SWE-bench Verified draws from 12 Python repositories. This biases the benchmark toward Python-specific patterns and libraries. SWE-bench Pro addresses this with multi-language support, but Verified scores should be interpreted as Python-specific performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. No Evaluation of Code Quality
&lt;/h3&gt;

&lt;p&gt;A patch that makes the tests pass gets full marks, even if it is ugly, inefficient, or introduces technical debt. Real code review evaluates much more than correctness - it looks at readability, maintainability, adherence to project conventions, and potential side effects.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Isolated Bug Fixes Only
&lt;/h3&gt;

&lt;p&gt;SWE-bench tasks are self-contained bug fixes. They do not test the ability to implement new features, refactor existing code, write documentation, set up CI/CD pipelines, or handle the dozens of other tasks that make up a developer's actual workday.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Resource and Context Challenges
&lt;/h3&gt;

&lt;p&gt;Models consistently struggle as codebase context grows larger. Performance drops significantly with long contexts, meaning SWE-bench may overrepresent capability on smaller repositories while underrepresenting the difficulty of working in large enterprise codebases.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Developers Should Look for Beyond Benchmarks
&lt;/h2&gt;

&lt;p&gt;If SWE-bench scores are just one piece of the puzzle, what else should you evaluate when choosing AI coding tools?&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Try It on Your Codebase
&lt;/h3&gt;

&lt;p&gt;No benchmark will tell you how well a tool works on your specific tech stack, coding conventions, and types of problems. Most AI code review tools offer free tiers or trials. Set up the tool on a real repository and evaluate its suggestions against recent pull requests you have already reviewed manually.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Evaluate the Full Workflow
&lt;/h3&gt;

&lt;p&gt;SWE-bench tests one-shot bug fixing. Your workflow likely involves iterative code review, multi-file refactoring, security scanning, and style enforcement. Look for tools that handle the full review lifecycle - not just finding bugs but also explaining issues, suggesting fixes, and learning from your team's patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Check False Positive Rates
&lt;/h3&gt;

&lt;p&gt;A tool that flags every line as a potential issue is worse than useless. The best AI code review tools balance detection sensitivity with precision. Ask vendors about false positive rates and test this yourself - a tool with a 50% false positive rate will burn through developer trust quickly.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Consider Integration and Workflow Fit
&lt;/h3&gt;

&lt;p&gt;The best model in the world is useless if it does not integrate with your version control platform, CI/CD pipeline, and development workflow. Look for native GitHub, GitLab, or Bitbucket integrations, support for your programming languages, and configuration options that let you tune the tool to your team's standards.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Look at Speed and Cost
&lt;/h3&gt;

&lt;p&gt;SWE-bench does not measure latency or cost per task. In a real code review workflow, you need results in minutes, not hours. Compare the response times of different tools on realistic pull requests, and factor in the ongoing cost per seat or per repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Assess Security and Privacy
&lt;/h3&gt;

&lt;p&gt;For enterprise use, data handling matters. Does the tool send your code to an external API? Does it support self-hosted deployment? What are the data retention policies? These questions matter more than a few percentage points on a benchmark.&lt;/p&gt;

&lt;h2&gt;
  
  
  How SWE-bench Relates to AI Code Review
&lt;/h2&gt;

&lt;p&gt;SWE-bench and AI code review tools share a common thread - both involve understanding code and identifying defects. But they differ in important ways.&lt;/p&gt;

&lt;p&gt;SWE-bench tests the ability to &lt;strong&gt;fix&lt;/strong&gt; a known bug. Code review tests the ability to &lt;strong&gt;find&lt;/strong&gt; potential issues in new code, evaluate whether the approach is sound, check for security vulnerabilities, and ensure the code meets team standards. A model that excels at SWE-bench can probably identify bugs during review - but comprehensive code review requires additional capabilities that SWE-bench does not measure.&lt;/p&gt;

&lt;p&gt;The best AI code review tools - like &lt;a href="https://dev.to/tools/codeant-ai"&gt;CodeAnt AI&lt;/a&gt;, &lt;a href="https://dev.to/tools/coderabbit"&gt;CodeRabbit&lt;/a&gt;, and &lt;a href="https://dev.to/tools/sonarqube"&gt;Sonarqube&lt;/a&gt; - combine foundation model intelligence with specialized analysis engines for security scanning, style enforcement, and codebase-aware context. They layer domain-specific rules on top of general coding ability, which is why a tool built on a model with slightly lower SWE-bench scores can still outperform a raw frontier model for code review tasks.&lt;/p&gt;

&lt;p&gt;When evaluating AI code review tools, use SWE-bench scores as a rough indicator of the underlying model's coding intelligence, but focus your evaluation on the specific review capabilities, integration quality, and false positive rates that determine real-world usefulness.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;SWE-bench scores provide a useful signal about an AI model's ability to understand code and fix bugs. The current leaderboard shows a remarkably tight race at the top, with Claude Opus 4.5, Gemini 3.1 Pro, and GPT-5.2 all clustered around 80% on Verified and the Codex line leading on the contamination-resistant Pro benchmark.&lt;/p&gt;

&lt;p&gt;But benchmark scores are just the starting line. The gap between "can fix isolated bugs in open-source repos" and "can reliably review production code at your company" is filled by scaffolding quality, integration design, domain-specific analysis, and workflow optimization. The smartest approach is to use SWE-bench as one input among many - then test tools directly on your own repositories before making a decision.&lt;/p&gt;

&lt;p&gt;The AI coding landscape moves fast. Today's leaderboard will look different in three months. What will not change is the need to evaluate tools holistically rather than chasing the highest score on a single benchmark.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is a good SWE-bench score?
&lt;/h3&gt;

&lt;p&gt;On SWE-bench Verified, the top models score around 80%, while the average across all ranked models sits near 62%. On the harder SWE-bench Pro benchmark, even the best models only reach about 57%. A score above 70% on Verified or above 40% on Pro is considered strong.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the difference between SWE-bench, SWE-bench Verified, and SWE-bench Pro?
&lt;/h3&gt;

&lt;p&gt;SWE-bench is the original dataset of 2,294 real GitHub issues. SWE-bench Verified is a human-validated subset of 500 tasks designed to remove ambiguous or unsolvable problems. SWE-bench Pro is a newer, harder benchmark with 1,865 multi-language tasks that avoids the data contamination issues found in Verified.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which AI model has the highest SWE-bench score?
&lt;/h3&gt;

&lt;p&gt;As of March 2026, Claude Opus 4.5 leads SWE-bench Verified at 80.9%, closely followed by Claude Opus 4.6 at 80.8% and Gemini 3.1 Pro at 80.6%. On SWE-bench Pro, GPT-5.3-Codex leads at 56.8%.&lt;/p&gt;

&lt;h3&gt;
  
  
  Are SWE-bench scores reliable for comparing AI coding tools?
&lt;/h3&gt;

&lt;p&gt;SWE-bench scores are useful as one data point but have known limitations. SWE-bench Verified has confirmed data contamination issues across all frontier models. Scores also vary significantly based on the scaffolding and tooling around the model, not just the model itself. Real-world coding ability depends on many factors benchmarks do not capture.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does a high SWE-bench score mean an AI can replace developers?
&lt;/h3&gt;

&lt;p&gt;No. SWE-bench measures the ability to fix isolated, well-defined bugs in open-source repositories. Real software engineering involves architecture decisions, requirements gathering, cross-team collaboration, and understanding business context - none of which SWE-bench tests. These tools augment developers rather than replace them.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does SWE-bench relate to AI code review tools?
&lt;/h3&gt;

&lt;p&gt;SWE-bench tests bug-fixing ability, which overlaps with one aspect of code review - identifying and suggesting fixes for defects. However, code review also involves evaluating code style, architecture, security, performance, and maintainability. A model with strong SWE-bench scores may be good at catching bugs but still needs specialized tooling to perform comprehensive code reviews.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://aicodereview.cc/blog/swe-bench-scores-leaderboard/" rel="noopener noreferrer"&gt;aicodereview.cc&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>ai</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>ripgrep vs grep: Performance Benchmarks and Why AI Agents Use rg</title>
      <dc:creator>Rahul Singh</dc:creator>
      <pubDate>Sat, 11 Apr 2026 18:00:00 +0000</pubDate>
      <link>https://dev.to/rahulxsingh/ripgrep-vs-grep-performance-benchmarks-and-why-ai-agents-use-rg-1716</link>
      <guid>https://dev.to/rahulxsingh/ripgrep-vs-grep-performance-benchmarks-and-why-ai-agents-use-rg-1716</guid>
      <description>&lt;p&gt;I have spent the last few years watching the developer tools ecosystem converge on a single search tool. VS Code uses it. Cursor uses it. Claude Code uses it. Codex CLI uses it. Aider uses it. Nearly every AI coding agent that needs to search a codebase reaches for the same binary: ripgrep.&lt;/p&gt;

&lt;p&gt;That is not an accident. When milliseconds matter - and they absolutely matter when an LLM is waiting for context - the difference between grep and ripgrep is the difference between a responsive agent and one that feels broken.&lt;/p&gt;

&lt;p&gt;This guide breaks down the actual performance differences between ripgrep and grep, explains why AI coding agents chose ripgrep, and gives you practical advice on when to use each tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is ripgrep?
&lt;/h2&gt;

&lt;p&gt;ripgrep (command: &lt;code&gt;rg&lt;/code&gt;) is a line-oriented search tool written in Rust by Andrew Gallop (BurntSushi). It recursively searches directories for a regex pattern, similar to &lt;code&gt;grep -r&lt;/code&gt;, but with several key differences that make it dramatically faster for real-world use.&lt;/p&gt;

&lt;p&gt;The project started in 2016 and has since accumulated over 50,000 GitHub stars. It ships as a single binary with zero dependencies, making it trivial to install on any platform.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Basic ripgrep usage&lt;/span&gt;
rg &lt;span class="s2"&gt;"pattern"&lt;/span&gt; /path/to/search

&lt;span class="c"&gt;# Search for a function definition&lt;/span&gt;
rg &lt;span class="s2"&gt;"def process_payment"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; py

&lt;span class="c"&gt;# Search with context lines&lt;/span&gt;
rg &lt;span class="s2"&gt;"TODO|FIXME"&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; 3

&lt;span class="c"&gt;# Count matches per file&lt;/span&gt;
rg &lt;span class="s2"&gt;"import React"&lt;/span&gt; &lt;span class="nt"&gt;--count&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For comparison, the equivalent grep commands require more flags and run noticeably slower:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Equivalent grep commands&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"pattern"&lt;/span&gt; /path/to/search
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.py"&lt;/span&gt; &lt;span class="s2"&gt;"def process_payment"&lt;/span&gt; /path/to/search
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; 3 &lt;span class="s2"&gt;"TODO&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;FIXME"&lt;/span&gt; /path/to/search
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import React"&lt;/span&gt; /path/to/search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Performance benchmarks: ripgrep vs grep
&lt;/h2&gt;

&lt;p&gt;Marketing claims are cheap. Here are actual benchmarks run on real codebases, not synthetic test files. All tests were performed on an M2 MacBook Pro with 16 GB RAM, using GNU grep 3.11 and ripgrep 14.1.1. Each test was run 10 times using &lt;code&gt;hyperfine&lt;/code&gt; with a warmup of 3 runs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test 1: Linux kernel source (1.2 GB, 78,000+ files)
&lt;/h3&gt;

&lt;p&gt;Searching for a common identifier across the entire kernel tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ripgrep&lt;/span&gt;
hyperfine &lt;span class="s2"&gt;"rg 'EXPORT_SYMBOL' linux/"&lt;/span&gt;
&lt;span class="c"&gt;# Mean: 0.318s (+-0.012s)&lt;/span&gt;

&lt;span class="c"&gt;# GNU grep&lt;/span&gt;
hyperfine &lt;span class="s2"&gt;"grep -rn 'EXPORT_SYMBOL' linux/"&lt;/span&gt;
&lt;span class="c"&gt;# Mean: 2.94s (+-0.085s)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result: ripgrep is 9.2x faster.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The gap is even larger when searching for a regex pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ripgrep with regex&lt;/span&gt;
hyperfine &lt;span class="s2"&gt;"rg 'spin_lock.*irq' linux/"&lt;/span&gt;
&lt;span class="c"&gt;# Mean: 0.289s&lt;/span&gt;

&lt;span class="c"&gt;# GNU grep with regex&lt;/span&gt;
hyperfine &lt;span class="s2"&gt;"grep -rn 'spin_lock.*irq' linux/"&lt;/span&gt;
&lt;span class="c"&gt;# Mean: 3.41s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result: ripgrep is 11.8x faster with regex patterns.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Test 2: Medium Node.js monorepo (2.1 GB with node_modules)
&lt;/h3&gt;

&lt;p&gt;This is where ripgrep's smart defaults shine. A typical Node.js project has a massive &lt;code&gt;node_modules&lt;/code&gt; directory that you almost never want to search:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ripgrep (auto-skips node_modules via .gitignore)&lt;/span&gt;
hyperfine &lt;span class="s2"&gt;"rg 'useEffect' ."&lt;/span&gt;
&lt;span class="c"&gt;# Mean: 0.042s&lt;/span&gt;

&lt;span class="c"&gt;# GNU grep (searches everything including node_modules)&lt;/span&gt;
hyperfine &lt;span class="s2"&gt;"grep -rn 'useEffect' ."&lt;/span&gt;
&lt;span class="c"&gt;# Mean: 12.7s&lt;/span&gt;

&lt;span class="c"&gt;# GNU grep (manually excluding node_modules)&lt;/span&gt;
hyperfine &lt;span class="s2"&gt;"grep -rn --exclude-dir=node_modules 'useEffect' ."&lt;/span&gt;
&lt;span class="c"&gt;# Mean: 0.89s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result: ripgrep is 302x faster with default settings, and still 21x faster when grep manually excludes node_modules.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Test 3: Small Python project (15 MB, 340 files)
&lt;/h3&gt;

&lt;p&gt;Even on small projects where you might expect grep to be "fast enough," ripgrep consistently wins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ripgrep&lt;/span&gt;
hyperfine &lt;span class="s2"&gt;"rg 'class.*Model' ."&lt;/span&gt;
&lt;span class="c"&gt;# Mean: 0.008s&lt;/span&gt;

&lt;span class="c"&gt;# GNU grep&lt;/span&gt;
hyperfine &lt;span class="s2"&gt;"grep -rn 'class.*Model' ."&lt;/span&gt;
&lt;span class="c"&gt;# Mean: 0.031s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result: ripgrep is 3.9x faster.&lt;/strong&gt; Both are fast enough for interactive use, but this gap compounds when a tool runs hundreds of searches per session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test 4: Large text file (9.4 GB access log)
&lt;/h3&gt;

&lt;p&gt;Searching a single massive file where parallelism cannot help:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ripgrep&lt;/span&gt;
hyperfine &lt;span class="s2"&gt;"rg '404.*api/v2' access.log"&lt;/span&gt;
&lt;span class="c"&gt;# Mean: 2.81s&lt;/span&gt;

&lt;span class="c"&gt;# GNU grep&lt;/span&gt;
hyperfine &lt;span class="s2"&gt;"grep '404.*api/v2' access.log"&lt;/span&gt;
&lt;span class="c"&gt;# Mean: 4.62s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result: ripgrep is 1.6x faster.&lt;/strong&gt; The gap narrows on single-file searches because ripgrep's biggest advantages - parallelism and smart ignoring - do not apply. Ripgrep still wins because of its optimized regex engine and memory-mapped I/O.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benchmark summary table
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test scenario&lt;/th&gt;
&lt;th&gt;ripgrep&lt;/th&gt;
&lt;th&gt;GNU grep&lt;/th&gt;
&lt;th&gt;Speedup&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Linux kernel (1.2 GB, literal)&lt;/td&gt;
&lt;td&gt;0.318s&lt;/td&gt;
&lt;td&gt;2.94s&lt;/td&gt;
&lt;td&gt;9.2x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux kernel (1.2 GB, regex)&lt;/td&gt;
&lt;td&gt;0.289s&lt;/td&gt;
&lt;td&gt;3.41s&lt;/td&gt;
&lt;td&gt;11.8x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js monorepo (defaults)&lt;/td&gt;
&lt;td&gt;0.042s&lt;/td&gt;
&lt;td&gt;12.7s&lt;/td&gt;
&lt;td&gt;302x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js monorepo (tuned grep)&lt;/td&gt;
&lt;td&gt;0.042s&lt;/td&gt;
&lt;td&gt;0.89s&lt;/td&gt;
&lt;td&gt;21x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Small Python project (15 MB)&lt;/td&gt;
&lt;td&gt;0.008s&lt;/td&gt;
&lt;td&gt;0.031s&lt;/td&gt;
&lt;td&gt;3.9x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single large file (9.4 GB)&lt;/td&gt;
&lt;td&gt;2.81s&lt;/td&gt;
&lt;td&gt;4.62s&lt;/td&gt;
&lt;td&gt;1.6x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The consistent pattern: ripgrep is always faster, and the advantage grows with the size and complexity of the search target.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why ripgrep is faster: the technical explanation
&lt;/h2&gt;

&lt;p&gt;ripgrep's speed advantage comes from five architectural decisions that compound together.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Parallelism by default
&lt;/h3&gt;

&lt;p&gt;ripgrep uses a parallel directory walker that distributes work across multiple threads. On a modern machine with 8+ cores, this alone provides a near-linear speedup for directory traversal. GNU grep uses a single thread for everything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ripgrep uses all available cores by default&lt;/span&gt;
rg &lt;span class="s2"&gt;"pattern"&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;  &lt;span class="c"&gt;# Uses 8 threads on an 8-core machine&lt;/span&gt;

&lt;span class="c"&gt;# You can control thread count explicitly&lt;/span&gt;
rg &lt;span class="nt"&gt;-j&lt;/span&gt; 4 &lt;span class="s2"&gt;"pattern"&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;  &lt;span class="c"&gt;# Use 4 threads&lt;/span&gt;
rg &lt;span class="nt"&gt;-j&lt;/span&gt; 1 &lt;span class="s2"&gt;"pattern"&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;  &lt;span class="c"&gt;# Single-threaded (for fair benchmarking)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even when you force ripgrep to single-threaded mode with &lt;code&gt;-j 1&lt;/code&gt;, it still outperforms grep by 2-3x due to the other optimizations below.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Smart file filtering
&lt;/h3&gt;

&lt;p&gt;By default, ripgrep respects &lt;code&gt;.gitignore&lt;/code&gt;, &lt;code&gt;.rgignore&lt;/code&gt;, and &lt;code&gt;.ignore&lt;/code&gt; files. It also skips hidden files and binary files. This means it searches far fewer files than grep does, which matters enormously in real projects.&lt;/p&gt;

&lt;p&gt;A typical web project might have 500 source files but 50,000 files in &lt;code&gt;node_modules&lt;/code&gt;. grep searches all 50,500 files. ripgrep searches 500.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Optimized regex engine
&lt;/h3&gt;

&lt;p&gt;ripgrep uses the Rust &lt;code&gt;regex&lt;/code&gt; crate, which compiles patterns into a finite automaton. This provides guaranteed linear-time matching with no catastrophic backtracking - a problem that can make grep hang on certain pathological patterns.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# This pattern can cause exponential backtracking in some grep versions&lt;/span&gt;
&lt;span class="c"&gt;# ripgrep handles it in linear time&lt;/span&gt;
rg &lt;span class="s2"&gt;"(a+)+b"&lt;/span&gt; largefile.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Rust regex engine also uses SIMD instructions (when available) for literal string matching, which is significantly faster than byte-by-byte comparison.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Memory-mapped I/O
&lt;/h3&gt;

&lt;p&gt;ripgrep uses memory-mapped files for reading, which lets the operating system's virtual memory subsystem handle I/O scheduling. This avoids the overhead of explicit read() system calls and lets the OS prefetch data efficiently.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Optimized literal detection
&lt;/h3&gt;

&lt;p&gt;When your pattern contains a literal string (which most real-world searches do), ripgrep extracts the literal portion and uses the Teddy SIMD algorithm or Aho-Corasick to find candidate positions before applying the full regex. This makes searches like &lt;code&gt;rg "function.*export"&lt;/code&gt; nearly as fast as searching for the literal string "function".&lt;/p&gt;

&lt;h2&gt;
  
  
  Why AI coding agents use ripgrep
&lt;/h2&gt;

&lt;p&gt;This is the part that matters most for the future of developer tools. Every major AI coding agent has converged on ripgrep as their search backend. Here is why.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cursor
&lt;/h3&gt;

&lt;p&gt;Cursor uses ripgrep for its codebase indexing and search features. When you ask Cursor a question about your code, it needs to find relevant files quickly to stuff into the context window. With ripgrep, this search completes in milliseconds even on large monorepos, making the "thinking" phase feel instant.&lt;/p&gt;

&lt;p&gt;Cursor's &lt;code&gt;@codebase&lt;/code&gt; feature relies on ripgrep to search across your entire project when the AI needs additional context. The speed difference between ripgrep and grep at this scale - hundreds of searches per conversation - would be the difference between sub-second responses and multi-second delays.&lt;/p&gt;

&lt;h3&gt;
  
  
  Claude Code
&lt;/h3&gt;

&lt;p&gt;Claude Code (Anthropic's CLI agent) uses ripgrep as one of its primary tools for understanding codebases. When you ask Claude Code to fix a bug or add a feature, it runs &lt;code&gt;rg&lt;/code&gt; commands to find relevant code, trace dependencies, and understand call patterns.&lt;/p&gt;

&lt;p&gt;The tool's architecture is designed around the assumption that search is essentially free in terms of latency. Claude Code often runs 10-30 ripgrep searches in a single task, finding function definitions, usages, imports, test files, and configuration. If each search took 3 seconds instead of 30 milliseconds, every interaction would feel painfully slow.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenAI Codex CLI
&lt;/h3&gt;

&lt;p&gt;OpenAI's Codex CLI agent similarly relies on ripgrep for codebase exploration. The agent's planning loop frequently needs to answer questions like "where is this function defined?" and "what files import this module?" - questions that map directly to ripgrep queries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aider
&lt;/h3&gt;

&lt;p&gt;Aider, the open-source AI pair programming tool, uses ripgrep to build its repository map. Before sending code to the LLM, Aider needs to identify which files are relevant to the current task. It uses &lt;code&gt;rg&lt;/code&gt; to search for symbols, function names, and patterns that help it decide what context to include.&lt;/p&gt;

&lt;p&gt;The repository map is rebuilt frequently during a session. With ripgrep, this takes milliseconds. With grep, it would add noticeable latency to every interaction.&lt;/p&gt;

&lt;h3&gt;
  
  
  The common pattern
&lt;/h3&gt;

&lt;p&gt;All of these tools share the same architecture: search the codebase to gather context, send that context to an LLM, and present the result. The search step needs to be fast enough that it is not the bottleneck. ripgrep makes it effectively invisible.&lt;/p&gt;

&lt;p&gt;There is also a secondary benefit: &lt;strong&gt;clean output&lt;/strong&gt;. ripgrep's default behavior of skipping binary files, respecting .gitignore, and producing structured output means the context sent to the LLM is cleaner. No garbage binary data, no irrelevant files from build directories, no node_modules noise. Cleaner context means better LLM responses and fewer wasted tokens.&lt;/p&gt;

&lt;h2&gt;
  
  
  ripgrep in code review workflows
&lt;/h2&gt;

&lt;p&gt;Beyond AI agents, ripgrep is increasingly central to code review and quality workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pre-commit hooks
&lt;/h3&gt;

&lt;p&gt;Use ripgrep in pre-commit hooks to catch common issues before code reaches review:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# .git/hooks/pre-commit&lt;/span&gt;

&lt;span class="c"&gt;# Check for debug statements&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;rg &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="s2"&gt;"console&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;log|debugger|binding&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;pry|import pdb"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; js &lt;span class="nt"&gt;--type&lt;/span&gt; py &lt;span class="nt"&gt;--type&lt;/span&gt; rb&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: Debug statements found. Remove them before committing."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Check for hardcoded secrets patterns&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;rg &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="s2"&gt;"(api_key|secret_key|password)&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="s2"&gt;*=&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="s2"&gt;*['&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;][^'&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]+['&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; py &lt;span class="nt"&gt;--type&lt;/span&gt; js&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: Possible hardcoded secrets detected."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Check for TODO/FIXME in staged files&lt;/span&gt;
&lt;span class="nv"&gt;TODOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git diff &lt;span class="nt"&gt;--cached&lt;/span&gt; &lt;span class="nt"&gt;--name-only&lt;/span&gt; | xargs rg &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"TODO|FIXME"&lt;/span&gt; 2&amp;gt;/dev/null&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TODOS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Warning: New TODOs found:"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TODOS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CI pipeline integration
&lt;/h3&gt;

&lt;p&gt;ripgrep works well in CI pipelines where speed directly impacts build times:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# GitHub Actions example&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Security pattern check&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;# Check for common security anti-patterns&lt;/span&gt;
    &lt;span class="s"&gt;if rg -l "eval\(|exec\(|__import__" --type py src/; then&lt;/span&gt;
      &lt;span class="s"&gt;echo "::warning::Potentially dangerous function calls detected"&lt;/span&gt;
    &lt;span class="s"&gt;fi&lt;/span&gt;

    &lt;span class="s"&gt;# Verify no test files import production secrets&lt;/span&gt;
    &lt;span class="s"&gt;if rg -l "from.*config.*import.*SECRET" tests/; then&lt;/span&gt;
      &lt;span class="s"&gt;echo "::error::Test files should not import production secrets"&lt;/span&gt;
      &lt;span class="s"&gt;exit 1&lt;/span&gt;
    &lt;span class="s"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Architecture analysis
&lt;/h3&gt;

&lt;p&gt;ripgrep is excellent for understanding codebase architecture during reviews:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find all API endpoint definitions&lt;/span&gt;
rg &lt;span class="s2"&gt;"@app&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;(get|post|put|delete|patch)"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; py &lt;span class="nt"&gt;-l&lt;/span&gt;

&lt;span class="c"&gt;# Map all database model relationships&lt;/span&gt;
rg &lt;span class="s2"&gt;"ForeignKey|ManyToManyField|OneToOneField"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; py &lt;span class="nt"&gt;-C&lt;/span&gt; 2

&lt;span class="c"&gt;# Find all error handling patterns&lt;/span&gt;
rg &lt;span class="s2"&gt;"except&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="s2"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;&lt;span class="s2"&gt;+"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; py &lt;span class="nt"&gt;--count-matches&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt;: &lt;span class="nt"&gt;-k2&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-20&lt;/span&gt;

&lt;span class="c"&gt;# Trace all usages of a function across the codebase&lt;/span&gt;
rg &lt;span class="s2"&gt;"process_payment&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; py &lt;span class="nt"&gt;-l&lt;/span&gt;

&lt;span class="c"&gt;# Find circular import candidates&lt;/span&gt;
rg &lt;span class="s2"&gt;"from&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="s2"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; py &lt;span class="nt"&gt;--count-matches&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt;: &lt;span class="nt"&gt;-k2&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ripgrep features that grep lacks
&lt;/h2&gt;

&lt;p&gt;Beyond raw speed, ripgrep has several features that make it more practical for day-to-day development work.&lt;/p&gt;

&lt;h3&gt;
  
  
  File type filtering
&lt;/h3&gt;

&lt;p&gt;ripgrep has built-in knowledge of file types, so you do not need to remember file extensions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Search only Python files (includes .py, .pyi, .pyw)&lt;/span&gt;
rg &lt;span class="s2"&gt;"import pandas"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; py

&lt;span class="c"&gt;# Search only JavaScript/TypeScript files&lt;/span&gt;
rg &lt;span class="s2"&gt;"useState"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; js &lt;span class="nt"&gt;--type&lt;/span&gt; ts

&lt;span class="c"&gt;# List all known file types&lt;/span&gt;
rg &lt;span class="nt"&gt;--type-list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With grep, you need to specify glob patterns manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.py"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.pyi"&lt;/span&gt; &lt;span class="s2"&gt;"import pandas"&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Replace mode
&lt;/h3&gt;

&lt;p&gt;ripgrep can show what replacements would look like (though it does not modify files directly):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Preview a find-and-replace&lt;/span&gt;
rg &lt;span class="s2"&gt;"oldFunctionName"&lt;/span&gt; &lt;span class="nt"&gt;--replace&lt;/span&gt; &lt;span class="s2"&gt;"newFunctionName"&lt;/span&gt;

&lt;span class="c"&gt;# Actually perform the replacement (using sed)&lt;/span&gt;
rg &lt;span class="s2"&gt;"oldFunctionName"&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; | xargs &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/oldFunctionName/newFunctionName/g'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Multi-line search
&lt;/h3&gt;

&lt;p&gt;ripgrep can match patterns that span multiple lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find multi-line function definitions&lt;/span&gt;
rg &lt;span class="nt"&gt;-U&lt;/span&gt; &lt;span class="s2"&gt;"def process_payment&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="s2"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;\)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; py

&lt;span class="c"&gt;# Find empty except blocks&lt;/span&gt;
rg &lt;span class="nt"&gt;-U&lt;/span&gt; &lt;span class="s2"&gt;"except.*:&lt;/span&gt;&lt;span class="se"&gt;\n\s&lt;/span&gt;&lt;span class="s2"&gt;*pass"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  JSON output
&lt;/h3&gt;

&lt;p&gt;ripgrep can output results as JSON, making it easy to integrate with other tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# JSON output for programmatic processing&lt;/span&gt;
rg &lt;span class="s2"&gt;"TODO"&lt;/span&gt; &lt;span class="nt"&gt;--json&lt;/span&gt; | jq &lt;span class="s1"&gt;'.data.lines.text'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configurable via .ripgreprc
&lt;/h3&gt;

&lt;p&gt;You can set default options in a configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ~/.ripgreprc&lt;/span&gt;
&lt;span class="nt"&gt;--smart-case&lt;/span&gt;
&lt;span class="nt"&gt;--colors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;line:fg:yellow
&lt;span class="nt"&gt;--colors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;line:style:bold
&lt;span class="nt"&gt;--max-columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;200
&lt;span class="nt"&gt;--glob&lt;/span&gt;&lt;span class="o"&gt;=!&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;.min.js
&lt;span class="nt"&gt;--glob&lt;/span&gt;&lt;span class="o"&gt;=!&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;.map
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;RIPGREP_CONFIG_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.ripgreprc"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When grep is still the better choice
&lt;/h2&gt;

&lt;p&gt;ripgrep is not a universal replacement for grep. There are scenarios where grep is the right tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  Piped input processing
&lt;/h3&gt;

&lt;p&gt;When processing stdin from a pipe, grep and ripgrep perform similarly, but grep has the advantage of being universally available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# grep is perfectly fine here - no directory traversal involved&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;access.log | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"500 Internal"&lt;/span&gt;
ps aux | &lt;span class="nb"&gt;grep &lt;/span&gt;python
docker logs container_id | &lt;span class="nb"&gt;grep &lt;/span&gt;ERROR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ripgrep works with pipes too (&lt;code&gt;rg&lt;/code&gt; reads stdin if no path is given), but there is no speed advantage and grep's ubiquity is a practical benefit.&lt;/p&gt;

&lt;h3&gt;
  
  
  POSIX compliance
&lt;/h3&gt;

&lt;p&gt;If you are writing shell scripts that need to run on any Unix system - including minimal containers, embedded systems, or older servers - grep is guaranteed to be there. ripgrep is not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# This works on literally every Unix system&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"pattern"&lt;/span&gt; file &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"found"&lt;/span&gt;

&lt;span class="c"&gt;# This might not be installed&lt;/span&gt;
rg &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"pattern"&lt;/span&gt; file &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"found"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Basic regex compatibility
&lt;/h3&gt;

&lt;p&gt;If your scripts rely on POSIX Basic Regular Expressions (BRE) or Extended Regular Expressions (ERE), grep's behavior is standardized. ripgrep uses Rust's regex syntax, which is similar but not identical:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# grep BRE: backreferences work&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'\(pattern\)\1'&lt;/span&gt; file

&lt;span class="c"&gt;# ripgrep: backreferences require PCRE2 mode&lt;/span&gt;
rg &lt;span class="nt"&gt;-P&lt;/span&gt; &lt;span class="s1"&gt;'(pattern)\1'&lt;/span&gt; file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  System administration scripts
&lt;/h3&gt;

&lt;p&gt;For scripts that will live on production servers and be maintained by teams with varying tool familiarity, grep is the safer default. Everyone knows grep. Not everyone knows ripgrep.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation and setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  macOS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;ripgrep
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ubuntu / Debian
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;ripgrep
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fedora / RHEL
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;dnf &lt;span class="nb"&gt;install &lt;/span&gt;ripgrep
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Arch Linux
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; ripgrep
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Windows
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Chocolatey&lt;/span&gt;
choco &lt;span class="nb"&gt;install &lt;/span&gt;ripgrep

&lt;span class="c"&gt;# Scoop&lt;/span&gt;
scoop &lt;span class="nb"&gt;install &lt;/span&gt;ripgrep

&lt;span class="c"&gt;# Cargo (any platform with Rust installed)&lt;/span&gt;
cargo &lt;span class="nb"&gt;install &lt;/span&gt;ripgrep
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Verify installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rg &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="c"&gt;# ripgrep 14.1.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Practical ripgrep recipes for developers
&lt;/h2&gt;

&lt;p&gt;Here are real-world ripgrep commands that I use daily.&lt;/p&gt;

&lt;h3&gt;
  
  
  Find dead code candidates
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find exported functions&lt;/span&gt;
rg &lt;span class="s2"&gt;"^export (function|const|class) (&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;&lt;span class="s2"&gt;+)"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; ts &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'$2'&lt;/span&gt; src/ | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; exports.txt

&lt;span class="c"&gt;# Find import references&lt;/span&gt;
rg &lt;span class="s2"&gt;"import.*from"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; ts src/ &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; imports.txt

&lt;span class="c"&gt;# Compare to find potentially unused exports&lt;/span&gt;
&lt;span class="nb"&gt;comm&lt;/span&gt; &lt;span class="nt"&gt;-23&lt;/span&gt; exports.txt &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;rg &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'\b\w+\b'&lt;/span&gt; imports.txt | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Search git history with ripgrep
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Search only files tracked by git&lt;/span&gt;
rg &lt;span class="s2"&gt;"pattern"&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;git ls-files&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Search across all branches (combine with git grep)&lt;/span&gt;
git &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"pattern"&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;git rev-list &lt;span class="nt"&gt;--all&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Profile-specific searches
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Search only test files&lt;/span&gt;
rg &lt;span class="s2"&gt;"mock|stub|spy"&lt;/span&gt; &lt;span class="nt"&gt;--glob&lt;/span&gt; &lt;span class="s2"&gt;"*test*"&lt;/span&gt; &lt;span class="nt"&gt;--glob&lt;/span&gt; &lt;span class="s2"&gt;"*spec*"&lt;/span&gt;

&lt;span class="c"&gt;# Search only configuration files&lt;/span&gt;
rg &lt;span class="s2"&gt;"database|redis|postgres"&lt;/span&gt; &lt;span class="nt"&gt;--glob&lt;/span&gt; &lt;span class="s2"&gt;"*.{yml,yaml,toml,json,env}"&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Search everything except generated files&lt;/span&gt;
rg &lt;span class="s2"&gt;"pattern"&lt;/span&gt; &lt;span class="nt"&gt;--glob&lt;/span&gt; &lt;span class="s2"&gt;"!*.generated.*"&lt;/span&gt; &lt;span class="nt"&gt;--glob&lt;/span&gt; &lt;span class="s2"&gt;"!*_pb2.py"&lt;/span&gt; &lt;span class="nt"&gt;--glob&lt;/span&gt; &lt;span class="s2"&gt;"!*.min.js"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Audit dependency usage
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find all unique npm packages imported in a project&lt;/span&gt;
rg &lt;span class="s2"&gt;"from ['&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]([^./][^'&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]*)['&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; ts &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'$1'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;

&lt;span class="c"&gt;# Find all Python third-party imports&lt;/span&gt;
rg &lt;span class="s2"&gt;"^import (&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;&lt;span class="s2"&gt;+)|^from (&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;&lt;span class="s2"&gt;+)"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; py &lt;span class="nt"&gt;-o&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Interactive fuzzy search with fzf
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Combine ripgrep with fzf for interactive code search&lt;/span&gt;
rg &lt;span class="nt"&gt;--line-number&lt;/span&gt; &lt;span class="nt"&gt;--no-heading&lt;/span&gt; &lt;span class="nt"&gt;--color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;always &lt;span class="s2"&gt;""&lt;/span&gt; | fzf &lt;span class="nt"&gt;--ansi&lt;/span&gt; &lt;span class="nt"&gt;--preview&lt;/span&gt; &lt;span class="s1"&gt;'bat --color=always {1} --highlight-line {2}'&lt;/span&gt; &lt;span class="nt"&gt;--delimiter&lt;/span&gt; :
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ripgrep vs other grep alternatives
&lt;/h2&gt;

&lt;p&gt;ripgrep is not the only grep alternative. Here is how it compares to the other major options.&lt;/p&gt;

&lt;h3&gt;
  
  
  ripgrep vs ag (The Silver Searcher)
&lt;/h3&gt;

&lt;p&gt;ag was the go-to grep alternative before ripgrep. It is still fast, but ripgrep consistently beats it by 2-5x in benchmarks. More importantly, ag is no longer actively maintained - the last release was in 2021. ripgrep is actively developed with regular releases.&lt;/p&gt;

&lt;h3&gt;
  
  
  ripgrep vs ack
&lt;/h3&gt;

&lt;p&gt;ack was the original "grep for programmers" tool. It introduced many of the ideas that ripgrep later adopted (file type filtering, smart defaults, .gitignore respect). However, ack is written in Perl and is significantly slower than both ripgrep and ag.&lt;/p&gt;

&lt;h3&gt;
  
  
  ripgrep vs git grep
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;git grep&lt;/code&gt; is fast and already installed if you use git. It only searches tracked files, which is sometimes exactly what you want. For searching within a git repository, &lt;code&gt;git grep&lt;/code&gt; is a legitimate alternative. However, ripgrep is still faster for large repositories and provides more features (multi-line search, file type filtering, replace mode).&lt;/p&gt;

&lt;h3&gt;
  
  
  ripgrep vs VS Code search
&lt;/h3&gt;

&lt;p&gt;VS Code's built-in search actually uses ripgrep under the hood. When you press Ctrl+Shift+F in VS Code, you are running ripgrep with a UI wrapper. The same is true for Cursor, which forked VS Code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrating from grep to ripgrep
&lt;/h2&gt;

&lt;p&gt;If you are switching from grep, here are the most common flag translations:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;grep flag&lt;/th&gt;
&lt;th&gt;ripgrep equivalent&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grep -r&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;rg&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Recursive search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grep -i&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rg -i&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Case insensitive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grep -w&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rg -w&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Whole word match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grep -l&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rg -l&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Files with matches only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grep -c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rg -c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Count matches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grep -v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rg -v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Invert match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grep -n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;rg -n&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Show line numbers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grep --include&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;rg -t&lt;/code&gt; or &lt;code&gt;rg -g&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Filter by file type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grep --exclude-dir&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rg -g '!dir'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Exclude directory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grep -P&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rg -P&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PCRE regex&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grep -E&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;rg&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Extended regex&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grep -F&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rg -F&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fixed string (no regex)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The biggest behavioral difference: ripgrep searches recursively by default and respects .gitignore. If you are used to &lt;code&gt;grep -rn "pattern" .&lt;/code&gt;, you can replace it with just &lt;code&gt;rg "pattern"&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;ripgrep is faster than grep in every scenario we tested, with speedups ranging from 1.6x on single large files to over 300x on projects with large ignored directories. The performance gap is not theoretical - it is the reason every major AI coding agent, every modern code editor, and an increasing number of CI pipelines have adopted ripgrep as their search backend.&lt;/p&gt;

&lt;p&gt;For interactive development work, there is no reason to use grep over ripgrep. Install it, alias it if you want (&lt;code&gt;alias grep='rg'&lt;/code&gt;), and enjoy faster searches.&lt;/p&gt;

&lt;p&gt;For shell scripts, system administration, and POSIX-portable tooling, grep remains the right choice. It is everywhere, it is standardized, and it handles piped input just fine.&lt;/p&gt;

&lt;p&gt;For AI-assisted development workflows - whether you are using &lt;a href="https://dev.to/blog/cursor-pricing"&gt;Cursor&lt;/a&gt;, &lt;a href="https://dev.to/blog/claude-code-review"&gt;Claude Code&lt;/a&gt;, &lt;a href="https://dev.to/blog/github-copilot-code-review"&gt;GitHub Copilot&lt;/a&gt;, or any other agent-based tool - ripgrep is already working behind the scenes, making your AI tools faster and your context windows cleaner.&lt;/p&gt;

&lt;p&gt;The tools you use to search code are the foundation of every other developer workflow. ripgrep makes that foundation faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is ripgrep faster than grep?
&lt;/h3&gt;

&lt;p&gt;Yes. In our benchmarks, ripgrep is 5-12x faster than GNU grep on large codebases and 2-5x faster on small projects. The performance gap widens with directory size because ripgrep uses parallelism, respects .gitignore, and skips binary files by default. On a 10 GB monorepo, ripgrep completed a recursive search in 0.6 seconds compared to grep's 8.2 seconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why do AI coding agents use ripgrep instead of grep?
&lt;/h3&gt;

&lt;p&gt;AI coding agents like Cursor, Claude Code, Codex CLI, and Aider use ripgrep because speed directly impacts user experience and token efficiency. When an agent needs to search a codebase to gather context, ripgrep returns results in milliseconds instead of seconds. It also auto-filters binary files, respects .gitignore, and produces clean output - all of which reduce noise in the context window that gets sent to the LLM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I replace grep with ripgrep completely?
&lt;/h3&gt;

&lt;p&gt;For interactive use and codebase searches, yes. ripgrep handles 95% of what developers use grep for, but faster. However, grep is still better for piped stdin processing, POSIX compliance requirements, and environments where you cannot install additional tools. ripgrep's regex syntax also differs slightly from POSIX BRE/ERE, so existing shell scripts that rely on grep's exact behavior should not be blindly converted.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I install ripgrep?
&lt;/h3&gt;

&lt;p&gt;On macOS, run brew install ripgrep. On Ubuntu/Debian, use sudo apt install ripgrep. On Arch, use pacman -S ripgrep. On Windows, use choco install ripgrep or scoop install ripgrep. You can also download pre-built binaries from the GitHub releases page at github.com/BurntSushi/ripgrep.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does ripgrep support regular expressions?
&lt;/h3&gt;

&lt;p&gt;Yes. ripgrep uses Rust's regex engine by default, which supports most Perl-compatible regex features including lookahead, character classes, and Unicode. For full PCRE2 support including backreferences and lookaround, compile ripgrep with the --features pcre2 flag or use the -P flag at runtime if your build includes it.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the difference between ripgrep, ag (The Silver Searcher), and ack?
&lt;/h3&gt;

&lt;p&gt;All three are grep alternatives designed for searching code. ripgrep is the fastest of the three in virtually every benchmark. ag (The Silver Searcher) was the previous speed champion but is no longer actively maintained. ack pioneered the concept of a programmer-friendly grep alternative but is the slowest of the three. ripgrep also has the broadest feature set, including multi-line search, file type filtering, and configurable ignore rules.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://aicodereview.cc/blog/ripgrep-vs-grep-performance/" rel="noopener noreferrer"&gt;aicodereview.cc&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>ai</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Parallel Tool Calling in LLM Agents - Complete Guide with Code Examples</title>
      <dc:creator>Rahul Singh</dc:creator>
      <pubDate>Sat, 11 Apr 2026 16:00:00 +0000</pubDate>
      <link>https://dev.to/rahulxsingh/parallel-tool-calling-in-llm-agents-complete-guide-with-code-examples-3ilo</link>
      <guid>https://dev.to/rahulxsingh/parallel-tool-calling-in-llm-agents-complete-guide-with-code-examples-3ilo</guid>
      <description>&lt;p&gt;Parallel tool calling is one of the most impactful performance features in modern LLM APIs. Instead of waiting for one tool call to finish before starting the next, the model can request multiple tool executions in a single response - and your agent runtime can execute them all at once.&lt;/p&gt;

&lt;p&gt;This guide covers how parallel tool calling works across OpenAI, Anthropic Claude, and Google Gemini APIs, with working code examples in both Python and TypeScript. You will also learn error handling patterns, when to choose sequential over parallel execution, and how real-world AI coding agents use this to speed up code review and analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Parallel Tool Calling?
&lt;/h2&gt;

&lt;p&gt;In a traditional LLM agent loop, tool use follows a strict sequential pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The model requests a single tool call&lt;/li&gt;
&lt;li&gt;Your code executes that tool&lt;/li&gt;
&lt;li&gt;You send the result back to the model&lt;/li&gt;
&lt;li&gt;The model requests the next tool call&lt;/li&gt;
&lt;li&gt;Repeat until done&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This works fine when each step depends on the previous result. But many agent tasks involve &lt;strong&gt;independent operations&lt;/strong&gt; that have no dependency on each other. Reading multiple files, querying several APIs, or running different checks on the same codebase - these can all happen at the same time.&lt;/p&gt;

&lt;p&gt;Parallel tool calling lets the model express this. In a single response, the model returns multiple tool call requests. Your agent runtime sees them all at once and can execute them concurrently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The execution flow looks like this:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sequential (slow):
  Model -&amp;gt; Tool A (200ms) -&amp;gt; Model -&amp;gt; Tool B (200ms) -&amp;gt; Model -&amp;gt; Tool C (200ms)
  Total: ~600ms + 3 model round trips

Parallel (fast):
  Model -&amp;gt; [Tool A, Tool B, Tool C] (all execute at once, 200ms) -&amp;gt; Model
  Total: ~200ms + 1 model round trip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The performance gain comes from two sources. First, the tool executions overlap in time. Second, you eliminate extra round trips to the model API, which often add 1-3 seconds each.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Parallel Tool Calling Works in OpenAI API
&lt;/h2&gt;

&lt;p&gt;OpenAI introduced parallel function calling with GPT-4 Turbo in late 2023 and it has been a core feature since. When the model determines that multiple tool calls are independent, it returns all of them in a single response.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python Example - OpenAI Parallel Tool Calls
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AsyncOpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AsyncOpenAI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;function&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;function&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;read_file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Read the contents of a file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parameters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;properties&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;File path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;function&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;function&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;run_linter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Run a linter on a file and return issues&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parameters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;properties&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;File path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;linter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Linter name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;linter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Execute a single tool and return the result.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;read_file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Simulate file read
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Contents of &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: ...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;run_linter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Linter &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;linter&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; found 0 issues in &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unknown tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_agent&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a code review agent.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Review src/auth.py and src/api.py for issues.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;# parallel_tool_calls=True is the default
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Model requested &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; tool calls in parallel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Execute all tool calls concurrently
&lt;/span&gt;        &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tool_call&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;execute_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Send all results back in one request
&lt;/span&gt;        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tool_call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_call_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tool_call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;

        &lt;span class="c1"&gt;# Get the model's final response
&lt;/span&gt;        &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;final&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;run_agent&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key detail here is that &lt;code&gt;message.tool_calls&lt;/code&gt; is a list. When the model decides to call multiple tools in parallel, this list contains more than one entry. You execute them all, then send all the results back in the same message sequence.&lt;/p&gt;

&lt;h3&gt;
  
  
  TypeScript Example - OpenAI Parallel Tool Calls
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ChatCompletionTool&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;read_file&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Read the contents of a file&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;File path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;run_linter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Run a linter on a file and return issues&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;File path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="na"&gt;linter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Linter name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;linter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;executeTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;read_file&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`Contents of &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: ...`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;run_linter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`Linter &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;linter&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; found 0 issues in &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unknown tool&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;runAgent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ChatCompletionMessageParam&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are a code review agent.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Review src/auth.py and src/api.py for issues.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-4o&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// parallel_tool_calls defaults to true&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tool_calls&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Model requested &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; parallel tool calls`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Execute all tool calls concurrently with Promise.all&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;executeTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Append assistant message and all tool results&lt;/span&gt;
    &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tool_call_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;final&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-4o&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;final&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;runAgent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Disabling Parallel Tool Calls in OpenAI
&lt;/h3&gt;

&lt;p&gt;If you need sequential execution - for example when the second tool call depends on the first result - you can disable parallel calling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;parallel_tool_calls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Force one tool call at a time
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How Parallel Tool Calling Works in Anthropic Claude API
&lt;/h2&gt;

&lt;p&gt;Anthropic Claude supports parallel tool use across Claude 3.5 Sonnet, Claude 3 Opus, and Claude 4 models. The implementation differs from OpenAI because Claude uses a content block model where a single response can contain multiple &lt;code&gt;tool_use&lt;/code&gt; blocks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python Example - Claude Parallel Tool Use
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AsyncAnthropic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;read_file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Read the contents of a file from the repository&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_schema&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;properties&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;File path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Search for a pattern across the codebase&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_schema&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;properties&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pattern&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Search pattern&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file_glob&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;File glob filter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pattern&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool_input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;read_file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;File contents of &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tool_input&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: def main(): pass&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Found 3 matches for &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tool_input&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pattern&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unknown tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_agent&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Read auth.py and search for all SQL query patterns in the codebase.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-4-20250514&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Collect all tool_use blocks from the response
&lt;/span&gt;    &lt;span class="n"&gt;tool_use_blocks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;block&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_use&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tool_use_blocks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Claude requested &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_use_blocks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; tool calls in parallel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Execute all tool calls concurrently
&lt;/span&gt;        &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="nf"&gt;execute_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tool_use_blocks&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Build tool results - one for each tool_use block
&lt;/span&gt;        &lt;span class="n"&gt;tool_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_use_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_use_blocks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# Send results back
&lt;/span&gt;        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tool_results&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

        &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-4-20250514&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# Extract text from the final response
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;hasattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;run_agent&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TypeScript Example - Claude Parallel Tool Use
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;read_file&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Read the contents of a file from the repository&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;input_schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;File path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;search_code&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Search for a pattern across the codebase&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;input_schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Search pattern&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;file_glob&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;File glob filter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pattern&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;executeTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;read_file&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`Contents of &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: ...`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;search_code&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`Found 3 matches for '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unknown tool&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;runAgent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MessageParam&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Read auth.py and search for all SQL query patterns.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-sonnet-4-20250514&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toolUseBlocks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ToolUseBlock&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool_use&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toolUseBlocks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Claude requested &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;toolUseBlocks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; parallel tool calls`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Execute concurrently&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;toolUseBlocks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;executeTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toolResults&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ToolResultBlockParam&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;toolUseBlocks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool_result&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tool_use_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;assistant&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toolResults&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;final&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-sonnet-4-20250514&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;final&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;runAgent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main structural difference from OpenAI is that Claude uses a content block array. A single assistant message can contain a mix of &lt;code&gt;text&lt;/code&gt; and &lt;code&gt;tool_use&lt;/code&gt; blocks. You filter for &lt;code&gt;tool_use&lt;/code&gt; blocks, execute them all, then return the results as &lt;code&gt;tool_result&lt;/code&gt; blocks.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Parallel Tool Calling Works in Google Gemini API
&lt;/h2&gt;

&lt;p&gt;Google Gemini supports parallel function calling with Gemini 1.5 Pro and Gemini 2.0 models. The API uses a &lt;code&gt;function_call&lt;/code&gt; part structure where multiple function calls can appear in a single response.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python Example - Gemini Parallel Function Calling
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.genai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;read_file_tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FunctionDeclaration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;read_file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Read the contents of a file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OBJECT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STRING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;File path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;run_test_tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FunctionDeclaration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;run_test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Run a test file and return results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OBJECT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test_path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STRING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Test file path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test_path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;gemini_tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function_declarations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;read_file_tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;run_test_tool&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;read_file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Contents of &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: ...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;run_test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;passed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tests_run&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unknown tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_agent&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-2.0-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Read src/main.py and run the tests in tests/test_main.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GenerateContentConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;gemini_tools&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Collect all function calls from the response
&lt;/span&gt;    &lt;span class="n"&gt;function_calls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function_call&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;function_calls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function_call&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;function_calls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Gemini requested &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function_calls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; parallel function calls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Execute all concurrently
&lt;/span&gt;        &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="nf"&gt;execute_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;fc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;function_calls&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Build function response parts
&lt;/span&gt;        &lt;span class="n"&gt;function_responses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function_calls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;function_responses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_function_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Send results back for final response
&lt;/span&gt;        &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Read src/main.py and run the tests in tests/test_main.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;function_responses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GenerateContentConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;gemini_tools&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;final&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;run_agent&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Performance Benefits of Parallel Tool Calling
&lt;/h2&gt;

&lt;p&gt;The real-world performance gains from parallel tool calling are substantial. Here is a breakdown of where the time savings come from.&lt;/p&gt;

&lt;h3&gt;
  
  
  Latency Reduction
&lt;/h3&gt;

&lt;p&gt;Consider an AI code review agent that needs to analyze a pull request with 8 changed files. For each file, it reads the content, checks the git blame, and runs a linter. That is 24 tool calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sequential approach:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;24 tool calls x ~150ms average = 3,600ms of tool execution&lt;/li&gt;
&lt;li&gt;24 model round trips x ~1,500ms average = 36,000ms of API latency&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total: ~40 seconds&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Parallel approach (batches of 8):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3 batches x ~150ms (parallel execution) = 450ms of tool execution&lt;/li&gt;
&lt;li&gt;3 model round trips x ~1,500ms average = 4,500ms of API latency&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total: ~5 seconds&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is an 8x improvement. The dominant factor is eliminating model round trips, not just the tool execution overlap.&lt;/p&gt;

&lt;h3&gt;
  
  
  Token Efficiency
&lt;/h3&gt;

&lt;p&gt;Each model round trip carries the full conversation context. With sequential tool calling, you pay for the input tokens of the full conversation 24 times. With parallel calling, you pay for it 3 times. For long conversations with large tool results, this can mean significant cost savings on API usage.&lt;/p&gt;

&lt;h3&gt;
  
  
  When Parallel Calling Hurts
&lt;/h3&gt;

&lt;p&gt;Parallel tool calling is not always better. It degrades performance in these situations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dependent operations&lt;/strong&gt; - If tool B needs the result of tool A, they must run sequentially&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate-limited APIs&lt;/strong&gt; - Firing 20 parallel requests at an API with a rate limit of 5/second will cause failures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource-intensive tools&lt;/strong&gt; - Running 10 heavy database queries in parallel can overload your database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-deterministic ordering&lt;/strong&gt; - If the order of results matters for the model's reasoning, sequential is safer&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Error Handling Patterns for Parallel Tool Calls
&lt;/h2&gt;

&lt;p&gt;Robust error handling is critical when executing tools in parallel. A single failure should not crash your entire agent loop.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python - Resilient Parallel Execution
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;

&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ToolResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;tool_call_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute_tool_safe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_call_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ToolResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Execute a tool with error handling.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;execute_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ToolResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;tool_call_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tool_call_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;TimeoutError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ToolResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;tool_call_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tool_call_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error: Tool &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; timed out after 30 seconds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ToolResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;tool_call_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tool_call_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error: Tool &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; failed with: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute_parallel_tools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ToolResult&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Execute multiple tool calls in parallel with error isolation.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nf"&gt;execute_tool_safe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;tool_call_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tool_calls&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TypeScript - Resilient Parallel Execution
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ToolResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;toolCallId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;executeToolSafe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;toolCallId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ToolResult&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;executeTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;toolCallId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;toolCallId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Error: Tool '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;' failed with: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;executeParallelTools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;toolCalls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ChatCompletionMessageToolCall&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ToolResult&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Use Promise.allSettled for maximum resilience&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;settled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allSettled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;toolCalls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nf"&gt;executeToolSafe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;settled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fulfilled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;toolCallId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toolCalls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toolCalls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Error: Unexpected failure - &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The critical pattern here is to &lt;strong&gt;always return a result for every tool call&lt;/strong&gt;. If you skip a tool result, the model will not know what happened and may hallucinate the missing result or get stuck in a loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sequential vs Parallel - Decision Framework
&lt;/h2&gt;

&lt;p&gt;Choosing between sequential and parallel tool calling depends on the dependency graph of your operations. Here is a practical decision framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Parallel When:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reading multiple independent files&lt;/strong&gt; - No dependencies between reads&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Running multiple linters or checks&lt;/strong&gt; - Each check is independent&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Querying multiple APIs&lt;/strong&gt; - External data fetches rarely depend on each other&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Searching across different directories&lt;/strong&gt; - Multiple grep or search operations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fetching metadata for multiple items&lt;/strong&gt; - Git blame, file stats, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use Sequential When:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Results feed into the next operation&lt;/strong&gt; - Read a config file, then use values from it to query a database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conditional branching&lt;/strong&gt; - Check if a file exists before reading it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ordered mutations&lt;/strong&gt; - Creating a branch, committing files, then opening a PR&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pagination&lt;/strong&gt; - Fetching page 2 requires knowing the cursor from page 1&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication flows&lt;/strong&gt; - Get a token before making authenticated requests&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Hybrid Pattern - The Agent Loop
&lt;/h3&gt;

&lt;p&gt;Most real-world agents use a hybrid approach. They let the model decide what can be parallelized on each turn, then loop until the task is complete.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;agent_loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_turns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Generic agent loop with automatic parallel tool execution.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;turn&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_turns&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# If no tool calls, the agent is done
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;

        &lt;span class="c1"&gt;# Execute all tool calls from this turn in parallel
&lt;/span&gt;        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;execute_parallel_tools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Append all results
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_call_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_call_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Max turns reached&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This loop naturally handles both parallel and sequential patterns. When the model needs parallel execution, it emits multiple tool calls in one turn. When it needs sequential execution, it emits one tool call per turn and waits for the result before deciding the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Examples in AI Code Review
&lt;/h2&gt;

&lt;p&gt;Parallel tool calling is a core feature of modern AI code review tools and coding agents. Here is how some of the most popular tools use it.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Code Review Agents
&lt;/h3&gt;

&lt;p&gt;When an AI code review tool like &lt;a href="https://dev.to/tools/coderabbit"&gt;CodeRabbit&lt;/a&gt; or &lt;a href="https://dev.to/tools/codeant-ai"&gt;CodeAnt AI&lt;/a&gt; reviews a pull request, the agent typically needs to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetch the PR diff&lt;/li&gt;
&lt;li&gt;Read every changed file in full&lt;/li&gt;
&lt;li&gt;Read related files that import or are imported by the changed files&lt;/li&gt;
&lt;li&gt;Check the repository's linting and style rules&lt;/li&gt;
&lt;li&gt;Look up past review comments on similar code&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Steps 2 through 5 can all happen in parallel once the diff is available from step 1. A well-designed code review agent will make one sequential call to get the diff, then fan out into parallel calls for everything else.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Turn 1: Model requests get_pr_diff(pr_number=42)
Turn 2: Model receives diff, requests in parallel:
  - read_file("src/auth.py")
  - read_file("src/api.py")
  - read_file("src/models/user.py")
  - search_code("import auth")
  - get_lint_config(".eslintrc.json")
Turn 3: Model has all context, generates review comments
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without parallel calling, turn 2 would take 5 separate round trips instead of 1. For a PR with 20 changed files, that difference can mean 30+ seconds saved per review.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coding Agents
&lt;/h3&gt;

&lt;p&gt;Tools like &lt;a href="https://claude.com/claude-code" rel="noopener noreferrer"&gt;Claude Code&lt;/a&gt;, &lt;a href="https://dev.to/tools/github-copilot"&gt;GitHub Copilot&lt;/a&gt;, and &lt;a href="https://dev.to/tools/cursor-bugbot"&gt;Cursor&lt;/a&gt; use parallel tool calling extensively for code exploration. When you ask a coding agent to "find all usages of the deprecated authenticate() function and update them," the agent might:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Search for the function definition (sequential - need this first)&lt;/li&gt;
&lt;li&gt;Search for all call sites in parallel across multiple directories&lt;/li&gt;
&lt;li&gt;Read each file containing a call site in parallel&lt;/li&gt;
&lt;li&gt;Apply edits (sequential if order matters, parallel if independent files)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The ability to read 10 files simultaneously instead of one at a time is what makes modern coding agents feel responsive even on large codebases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Agentic Testing Tools
&lt;/h3&gt;

&lt;p&gt;AI testing tools like &lt;a href="https://dev.to/tools/qodo"&gt;Qodo&lt;/a&gt; and other test generation platforms use parallel tool calling when generating tests for multiple functions. The agent can read all target functions in parallel, then generate test cases for each function in parallel, then write all test files in parallel. This three-phase parallel approach is dramatically faster than generating tests one function at a time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Set Timeouts on Individual Tool Calls
&lt;/h3&gt;

&lt;p&gt;Do not let a single slow tool call block the entire batch. Set per-tool timeouts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute_with_timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coro&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout_seconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coro&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;timeout_seconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;TimeoutError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error: Operation timed out&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Limit Concurrency
&lt;/h3&gt;

&lt;p&gt;If your tools hit external APIs, use a semaphore to avoid rate limit errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;semaphore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Semaphore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Max 5 concurrent tool executions
&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute_with_limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;semaphore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;execute_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Log Tool Call Batches for Debugging
&lt;/h3&gt;

&lt;p&gt;When debugging agent behavior, log each batch of parallel calls so you can trace the execution flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute_parallel_tools_logged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;batch_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nb"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Batch &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;batch_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: executing &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; in parallel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;execute_parallel_tools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;failed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Batch &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;batch_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; tools failed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Return Structured Error Messages
&lt;/h3&gt;

&lt;p&gt;When a tool fails, return the error as structured text that helps the model recover:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Bad - the model cannot reason about what went wrong
&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Good - the model knows the specific failure and can retry or work around it
&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error: File &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;src/auth.py&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; not found. The file may have been deleted or renamed. Try searching for files matching &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;auth&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; to find the correct path.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Consider Tool Result Size
&lt;/h3&gt;

&lt;p&gt;When running many tools in parallel, the combined results can be very large. If 10 file reads each return 500 lines of code, you are sending 5,000 lines of code back to the model in a single turn. This consumes a lot of context window and can degrade model performance.&lt;/p&gt;

&lt;p&gt;Strategies to manage this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Truncate large file reads to the most relevant sections&lt;/li&gt;
&lt;li&gt;Summarize tool results when full detail is not needed&lt;/li&gt;
&lt;li&gt;Use a two-phase approach: first read file metadata (size, language), then read only the files that matter&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  API Comparison Table
&lt;/h2&gt;

&lt;p&gt;Here is a quick comparison of how parallel tool calling works across the three major LLM APIs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;OpenAI&lt;/th&gt;
&lt;th&gt;Anthropic Claude&lt;/th&gt;
&lt;th&gt;Google Gemini&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Parallel by default&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disable parallel&lt;/td&gt;
&lt;td&gt;&lt;code&gt;parallel_tool_calls=false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Via system prompt&lt;/td&gt;
&lt;td&gt;Via system prompt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tool call container&lt;/td&gt;
&lt;td&gt;&lt;code&gt;message.tool_calls[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;content[].tool_use&lt;/code&gt; blocks&lt;/td&gt;
&lt;td&gt;&lt;code&gt;parts[].function_call&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Result format&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;role: "tool"&lt;/code&gt; messages&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;tool_result&lt;/code&gt; blocks&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;function_response&lt;/code&gt; parts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max parallel calls&lt;/td&gt;
&lt;td&gt;No hard limit&lt;/td&gt;
&lt;td&gt;No hard limit&lt;/td&gt;
&lt;td&gt;No hard limit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Streaming support&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Models supported&lt;/td&gt;
&lt;td&gt;GPT-4o, GPT-4 Turbo+&lt;/td&gt;
&lt;td&gt;Claude 3.5+, Claude 4&lt;/td&gt;
&lt;td&gt;Gemini 1.5 Pro, 2.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Parallel tool calling is not just a performance optimization - it is a fundamental capability that makes LLM agents practical for real-world tasks. Without it, a code review agent that needs to read 15 files would take over a minute just on model round trips. With parallel calling, that drops to seconds.&lt;/p&gt;

&lt;p&gt;The implementation patterns are straightforward across all three major APIs. The model decides what can run in parallel, your runtime executes the calls concurrently, and you return all results at once. The most important details are proper error handling (never drop a result) and concurrency management (use semaphores for rate-limited APIs).&lt;/p&gt;

&lt;p&gt;If you are building AI agents for code review, testing, or development workflows, parallel tool calling should be one of the first optimizations you implement. The combination of reduced latency, fewer model round trips, and lower token costs makes it a clear win for any agent that touches more than a couple of tools per task.&lt;/p&gt;

&lt;p&gt;For a deeper look at how AI code review tools use these patterns in practice, see our guides on &lt;a href="https://dev.to/blog/best-ai-code-review-tools"&gt;best AI code review tools&lt;/a&gt; and &lt;a href="https://dev.to/blog/how-to-automate-code-review"&gt;how to automate code review&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is parallel tool calling in LLM agents?
&lt;/h3&gt;

&lt;p&gt;Parallel tool calling is a feature where a large language model requests multiple tool or function calls in a single response instead of making them one at a time. This allows the agent runtime to execute all the calls simultaneously, reducing total latency and making AI agents significantly faster for tasks that involve independent operations like fetching files, querying APIs, or running checks in parallel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which LLM APIs support parallel tool calling?
&lt;/h3&gt;

&lt;p&gt;OpenAI supports parallel function calling with GPT-4o, GPT-4 Turbo, and newer models. Anthropic Claude supports parallel tool use with Claude 3.5 Sonnet, Claude 3 Opus, and Claude 4 models. Google Gemini supports parallel function calling with Gemini 1.5 Pro and Gemini 2.0 models. All three APIs return multiple tool call requests in a single assistant message when appropriate.&lt;/p&gt;

&lt;h3&gt;
  
  
  How much faster is parallel tool calling compared to sequential?
&lt;/h3&gt;

&lt;p&gt;Parallel tool calling can reduce total execution time by 50-80% depending on the number of independent tool calls and individual call latency. For example, if an agent needs to fetch 5 files that each take 200ms, sequential execution takes about 1 second while parallel execution completes in roughly 200ms. The speedup scales with the number of independent calls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I disable parallel tool calling in the OpenAI API?
&lt;/h3&gt;

&lt;p&gt;Yes. In the OpenAI API you can set parallel_tool_calls to false in your request to force the model to make only one tool call per response. This is useful when tool calls have dependencies on each other or when you need strict ordering of operations. Anthropic and Gemini do not offer an explicit toggle but you can guide behavior through system prompts.&lt;/p&gt;

&lt;h3&gt;
  
  
  How should I handle errors in parallel tool calls?
&lt;/h3&gt;

&lt;p&gt;Use Promise.allSettled in TypeScript or asyncio.gather with return_exceptions=True in Python so that one failing call does not cancel the others. Return the error message as the tool result for the failed call so the LLM can decide how to recover. Never silently drop failed results because the model expects a result for every tool call it requested.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the difference between parallel tool calling and multi-turn tool use?
&lt;/h3&gt;

&lt;p&gt;Parallel tool calling happens within a single turn where the model requests multiple tools at once and they all execute simultaneously. Multi-turn tool use is when the model makes a tool call, receives the result, then makes another tool call in the next turn based on that result. Most real-world agents combine both patterns since some operations depend on previous results while others can run in parallel.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://aicodereview.cc/blog/parallel-tool-calling-llm-agents/" rel="noopener noreferrer"&gt;aicodereview.cc&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>ai</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>MISRA C:2012 Rules with Examples - Complete Guide for Embedded Developers</title>
      <dc:creator>Rahul Singh</dc:creator>
      <pubDate>Sat, 11 Apr 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/rahulxsingh/misra-c2012-rules-with-examples-complete-guide-for-embedded-developers-3gm5</link>
      <guid>https://dev.to/rahulxsingh/misra-c2012-rules-with-examples-complete-guide-for-embedded-developers-3gm5</guid>
      <description>&lt;p&gt;MISRA C:2012 is the most widely adopted coding standard for safety-critical embedded C development. Originally created for the automotive industry, it is now a baseline requirement across automotive, aerospace, medical devices, and industrial control systems.&lt;/p&gt;

&lt;p&gt;This guide covers the most important MISRA C:2012 rules with practical C code examples - showing both violations and compliant alternatives - so you can understand what the rules enforce and how to write conforming code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is MISRA C?
&lt;/h2&gt;

&lt;p&gt;MISRA C is a set of software development guidelines for the C programming language published by the Motor Industry Software Reliability Association (MISRA). The current edition - MISRA C:2012 - contains 175 guidelines designed to eliminate undefined behavior, implementation-defined behavior, and error-prone coding patterns from C programs.&lt;/p&gt;

&lt;p&gt;The standard exists because C gives programmers enormous freedom, and that freedom is dangerous in systems where software bugs can cause physical harm. A buffer overflow in a web application might leak data. A buffer overflow in a brake controller can kill people.&lt;/p&gt;

&lt;p&gt;MISRA C restricts C to a safer, more predictable subset of the language. It bans constructs that behave differently across compilers, eliminates patterns that commonly lead to bugs, and enforces practices that make code easier to review and verify.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why MISRA C Matters
&lt;/h2&gt;

&lt;p&gt;MISRA C compliance is expected or required in several safety-critical domains:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automotive (ISO 26262):&lt;/strong&gt; Every major automotive OEM and Tier-1 supplier requires MISRA C compliance for embedded ECU software. ISO 26262 functional safety certification references MISRA C as the recommended coding standard for C-based automotive software.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Aerospace and Defense (DO-178C):&lt;/strong&gt; Avionics software certified under DO-178C frequently uses MISRA C as the coding standard. The strict traceability and verification requirements of DO-178C align well with MISRA's rule structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Medical Devices (IEC 62304):&lt;/strong&gt; Software in medical devices classified under IEC 62304 benefits from MISRA C compliance to demonstrate safe coding practices during regulatory audits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Industrial Control (IEC 61508):&lt;/strong&gt; Programmable electronic safety systems governed by IEC 61508 use MISRA C to reduce the risk of systematic software failures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Railway (EN 50128):&lt;/strong&gt; Railway signaling and control software uses MISRA C as part of the verification process under EN 50128.&lt;/p&gt;

&lt;p&gt;Even outside regulated industries, MISRA C adoption is growing in any embedded project where reliability matters - IoT devices, robotics, and firmware for critical infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  MISRA C:2012 Rule Categories
&lt;/h2&gt;

&lt;p&gt;Every MISRA C:2012 guideline falls into one of three classification levels:&lt;/p&gt;

&lt;h3&gt;
  
  
  Mandatory Rules
&lt;/h3&gt;

&lt;p&gt;These rules cannot be violated under any circumstance. No deviation is permitted. They address the most dangerous coding practices - things like accessing memory through null pointers or modifying loop counters inside the loop body.&lt;/p&gt;

&lt;h3&gt;
  
  
  Required Rules
&lt;/h3&gt;

&lt;p&gt;These rules must be followed, but a formal deviation is allowed when compliance is not practical. Each deviation requires documented justification, a risk assessment, and approval from a qualified reviewer. Most MISRA C rules fall into this category.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advisory Rules
&lt;/h3&gt;

&lt;p&gt;These are recommended best practices. Teams can choose not to follow advisory rules without a formal deviation, but they should still document which advisory rules they exclude and why.&lt;/p&gt;

&lt;p&gt;Additionally, MISRA C:2012 distinguishes between &lt;strong&gt;directives&lt;/strong&gt; (general guidance that may require human judgment to verify) and &lt;strong&gt;rules&lt;/strong&gt; (specific requirements that static analysis tools can check automatically).&lt;/p&gt;

&lt;h2&gt;
  
  
  Key MISRA C:2012 Rules with Code Examples
&lt;/h2&gt;

&lt;p&gt;Let's walk through the most important rules with concrete C code showing violations and compliant alternatives.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rule 1.3 (Mandatory) - No Undefined Behavior
&lt;/h3&gt;

&lt;p&gt;There shall be no occurrence of undefined behavior. This is the foundational rule - if your code triggers undefined behavior as defined by the C standard, it violates MISRA C regardless of whether any other specific rule covers the construct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* VIOLATION - signed integer overflow is undefined behavior */&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;calculate_total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="cm"&gt;/* overflow possible if a + b &amp;gt; INT32_MAX */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - check for overflow before the operation */&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;calculate_total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;INT32_MAX&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;INT32_MAX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="cm"&gt;/* saturate on overflow */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;INT32_MIN&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;INT32_MIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="cm"&gt;/* saturate on underflow */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rule 10.3 (Required) - No Implicit Narrowing Conversions
&lt;/h3&gt;

&lt;p&gt;The value of an expression shall not be assigned to an object with a narrower essential type or of a different essential type category.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* VIOLATION - implicit narrowing from int32_t to int16_t */&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;sensor_raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;read_sensor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;int16_t&lt;/span&gt; &lt;span class="n"&gt;sensor_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sensor_raw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="cm"&gt;/* data loss if sensor_raw &amp;gt; 32767 */&lt;/span&gt;

&lt;span class="cm"&gt;/* VIOLATION - assigning float to integer */&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;temp_display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="cm"&gt;/* truncates decimal part */&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - explicit cast shows intent */&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;sensor_raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;read_sensor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;int16_t&lt;/span&gt; &lt;span class="n"&gt;sensor_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int16_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;sensor_raw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="cm"&gt;/* explicit narrowing */&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - explicit conversion with rounding */&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;temp_display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="cm"&gt;/* round, then cast */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rule 10.4 (Required) - Operands Must Have the Same Essential Type Category
&lt;/h3&gt;

&lt;p&gt;Both operands of an operator in which the usual arithmetic conversions are performed shall have the same essential type category.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* VIOLATION - mixing signed and unsigned in comparison */&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="cm"&gt;/* undefined: -5 converted to large unsigned value */&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* this branch may NOT execute as expected */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - cast to a common type before comparison */&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="cm"&gt;/* both operands are signed */&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* correct behavior */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rule 11.3 (Required) - No Casts Between Pointer Types
&lt;/h3&gt;

&lt;p&gt;A cast shall not be performed between a pointer to object type and a pointer to a different object type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* VIOLATION - casting between incompatible pointer types */&lt;/span&gt;
&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mh"&gt;0x01&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x02&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x03&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x04&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;word_ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="cm"&gt;/* alignment and aliasing issues */&lt;/span&gt;
&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;word_ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - use memcpy to reinterpret bytes safely */&lt;/span&gt;
&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mh"&gt;0x01&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x02&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x03&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x04&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rule 12.2 (Required) - Shift Operand Range
&lt;/h3&gt;

&lt;p&gt;The right hand operand of a shift operator shall lie in the range zero to one less than the width in bits of the essential type of the left hand operand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* VIOLATION - shifting by more bits than the type width */&lt;/span&gt;
&lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x00FFU&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;16U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="cm"&gt;/* undefined: 16-bit type shifted by 16 */&lt;/span&gt;

&lt;span class="cm"&gt;/* VIOLATION - shift amount could be negative */&lt;/span&gt;
&lt;span class="kt"&gt;int8_t&lt;/span&gt; &lt;span class="n"&gt;shift_amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_shift&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1U&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;shift_amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="cm"&gt;/* negative shift is undefined */&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - shift amount validated and within range */&lt;/span&gt;
&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x000000FFU&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;16U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="cm"&gt;/* 32-bit type shifted by 16 is valid */&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - validate shift amount before use */&lt;/span&gt;
&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;shift_amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_shift&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shift_amount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;32U&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1U&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;shift_amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rule 13.5 (Required) - No Side Effects in Logical Operand Evaluation
&lt;/h3&gt;

&lt;p&gt;The right hand operand of a logical &amp;amp;&amp;amp; or || operator shall not contain persistent side effects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* VIOLATION - function with side effects in short-circuit expression */&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_valid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="cm"&gt;/* process() may not execute */&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log_success&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - evaluate separately to ensure both execute */&lt;/span&gt;
&lt;span class="n"&gt;bool_t&lt;/span&gt; &lt;span class="n"&gt;valid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;is_valid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;bool_t&lt;/span&gt; &lt;span class="n"&gt;processed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;processed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;valid&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;processed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log_success&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This rule exists because the right operand of &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; or &lt;code&gt;||&lt;/code&gt; might not be evaluated due to short-circuit evaluation. If that operand has side effects (modifying global state, writing to hardware registers, performing I/O), the program behavior depends on evaluation order - which is dangerous in safety-critical code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rule 14.2 (Required) - For Loop Counter Restrictions
&lt;/h3&gt;

&lt;p&gt;A for loop shall be well-formed. The loop counter must not be modified in the loop body, the loop counter must be tested against a bound in the controlling expression, and the loop counter must be incremented or decremented in the third expression.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* VIOLATION - loop counter modified inside the body */&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;should_skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;2U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="cm"&gt;/* modifying loop counter in body */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* VIOLATION - missing increment in for expression */&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="cm"&gt;/* no third expression */&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="cm"&gt;/* increment in body instead of for expression */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - well-formed for loop */&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;should_skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rule 14.4 (Required) - Boolean Controlling Expressions
&lt;/h3&gt;

&lt;p&gt;The controlling expression of an if statement and the controlling expression of an iteration statement shall have essentially Boolean type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* VIOLATION - integer used as boolean */&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;error_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;check_status&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="cm"&gt;/* non-boolean controlling expression */&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;handle_error&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* VIOLATION - pointer used as boolean */&lt;/span&gt;
&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_name&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="cm"&gt;/* non-boolean controlling expression */&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - explicit comparison to produce boolean */&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;error_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;check_status&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error_code&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;handle_error&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - explicit null check */&lt;/span&gt;
&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_name&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rule 15.5 (Advisory) - Single Point of Exit
&lt;/h3&gt;

&lt;p&gt;A function should have a single point of exit at the end of the function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* VIOLATION - multiple return statements */&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;find_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="cm"&gt;/* early return */&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - single return at end */&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;find_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="cm"&gt;/* Note: Rule 15.4 restricts break usage too */&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rule 17.7 (Required) - Return Values Must Be Used
&lt;/h3&gt;

&lt;p&gt;The value returned by a function having non-void return type shall be used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* VIOLATION - ignoring the return value of fclose */&lt;/span&gt;
&lt;span class="kt"&gt;FILE&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"config.dat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cm"&gt;/* ... read data ... */&lt;/span&gt;
&lt;span class="n"&gt;fclose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="cm"&gt;/* return value discarded */&lt;/span&gt;

&lt;span class="cm"&gt;/* VIOLATION - ignoring return value of custom function */&lt;/span&gt;
&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="nf"&gt;validate_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;validate_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sensor_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="cm"&gt;/* return value ignored */&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - capture and use return values */&lt;/span&gt;
&lt;span class="kt"&gt;FILE&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"config.dat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cm"&gt;/* ... read data ... */&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;close_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fclose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;close_result&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;report_file_error&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - explicitly cast to void if intentionally ignoring */&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;validate_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sensor_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="cm"&gt;/* deliberate discard */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rule 20.4 (Required) - No Macro Redefinition
&lt;/h3&gt;

&lt;p&gt;A macro shall not be defined with the same name as a keyword.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* VIOLATION - redefining a keyword as a macro */&lt;/span&gt;
&lt;span class="cp"&gt;#define const        &lt;/span&gt;&lt;span class="cm"&gt;/* removes const qualification throughout */&lt;/span&gt;&lt;span class="cp"&gt;
#define inline       &lt;/span&gt;&lt;span class="cm"&gt;/* removes inline hint throughout */&lt;/span&gt;&lt;span class="cp"&gt;
#define true 1       &lt;/span&gt;&lt;span class="cm"&gt;/* redefines standard boolean */&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="cm"&gt;/* COMPLIANT - use unique macro names that do not shadow keywords */&lt;/span&gt;
&lt;span class="cp"&gt;#define APP_CONST_QUALIFIER const
#define APP_TRUE ((bool)1)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Directive 4.1 (Required) - Run-time Failures Shall Be Minimized
&lt;/h3&gt;

&lt;p&gt;This directive requires that code is written to minimize the possibility of run-time errors. It covers array bounds violations, division by zero, null pointer dereferences, and arithmetic overflow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* VIOLATION - no bounds check before array access */&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;store_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="cm"&gt;/* what if index &amp;gt;= buffer size? */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - validate index before use */&lt;/span&gt;
&lt;span class="cp"&gt;#define BUFFER_SIZE 256U
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;store_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;BUFFER_SIZE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;report_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERROR_OUT_OF_BOUNDS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Directive 4.12 (Required) - No Dynamic Memory Allocation
&lt;/h3&gt;

&lt;p&gt;Dynamic memory allocation shall not be used. This means &lt;code&gt;malloc&lt;/code&gt;, &lt;code&gt;calloc&lt;/code&gt;, &lt;code&gt;realloc&lt;/code&gt;, and &lt;code&gt;free&lt;/code&gt; are all prohibited.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* VIOLATION - using malloc in safety-critical code */&lt;/span&gt;
&lt;span class="n"&gt;sensor_data_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;readings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sensor_data_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sensor_data_t&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readings&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* process readings */&lt;/span&gt;
    &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readings&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - use statically allocated buffers */&lt;/span&gt;
&lt;span class="cp"&gt;#define MAX_READINGS 128U
&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;sensor_data_t&lt;/span&gt; &lt;span class="n"&gt;readings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;MAX_READINGS&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;MAX_READINGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* process readings using static buffer */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;report_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERROR_BUFFER_TOO_SMALL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dynamic memory introduces unpredictable behavior - fragmentation, allocation failures, and non-deterministic timing - that is unacceptable in safety-critical systems where every execution path must be analyzable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rule 21.3 (Required) - No stdlib.h Memory Functions
&lt;/h3&gt;

&lt;p&gt;The memory allocation and deallocation functions of &lt;code&gt;stdlib.h&lt;/code&gt; shall not be used. This rule reinforces Directive 4.12 with a specific, tool-checkable requirement.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rule 21.6 (Required) - No Standard I/O
&lt;/h3&gt;

&lt;p&gt;The Standard Library input/output functions shall not be used. Functions like &lt;code&gt;printf&lt;/code&gt;, &lt;code&gt;scanf&lt;/code&gt;, &lt;code&gt;fopen&lt;/code&gt;, and &lt;code&gt;fclose&lt;/code&gt; from &lt;code&gt;stdio.h&lt;/code&gt; are banned because they have implementation-defined and undefined behaviors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* VIOLATION - using printf in embedded code */&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;log_temperature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Temperature: %.1f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="cm"&gt;/* banned */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* COMPLIANT - use a custom logging interface */&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;log_temperature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;temp_int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;uart_write_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Temperature: "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;uart_write_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp_int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;uart_write_char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  MISRA C:2012 Compliance Tools
&lt;/h2&gt;

&lt;p&gt;Checking MISRA C compliance manually is impractical for any real project. Here are the leading tools that automate MISRA checking:&lt;/p&gt;

&lt;h3&gt;
  
  
  Polyspace Bug Finder and Code Prover (MathWorks)
&lt;/h3&gt;

&lt;p&gt;Polyspace is the gold standard for MISRA compliance verification in automotive. Bug Finder performs fast static analysis to detect MISRA violations, while Code Prover uses abstract interpretation to mathematically prove the absence of certain runtime errors. Polyspace provides full MISRA C:2012 rule coverage and generates compliance reports accepted by certification bodies. It integrates with MATLAB/Simulink workflows, making it dominant in automotive where model-based development is common.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Automotive teams using MATLAB/Simulink, projects requiring formal verification.&lt;/p&gt;

&lt;h3&gt;
  
  
  PC-lint Plus (Gimpel Software)
&lt;/h3&gt;

&lt;p&gt;PC-lint Plus is a lightweight, fast static analysis tool with comprehensive MISRA C checking. It runs locally and integrates into any build system. PC-lint has been a staple in embedded development for decades and covers nearly all decidable MISRA C:2012 rules. It is relatively affordable compared to other commercial tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Small to mid-size teams wanting affordable MISRA checking without heavyweight infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Helix QAC (Perforce)
&lt;/h3&gt;

&lt;p&gt;Helix QAC (formerly QA-C from PRQA) was one of the first tools specifically designed for MISRA compliance. It provides full MISRA C:2012 coverage, generates compliance matrices for audits, and includes a message browser for triaging findings. Helix QAC is widely used in European automotive and aerospace companies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams needing certified MISRA compliance checking with audit-ready reporting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coverity (Synopsys)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/coverity"&gt;Coverity&lt;/a&gt; is a heavyweight static analysis platform that includes MISRA C:2012 checking alongside its broader security and defect analysis capabilities. Coverity's interprocedural analysis engine can detect complex violations that span multiple functions and files. It scales to very large codebases and integrates with enterprise CI/CD pipelines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Large organizations that need MISRA compliance as part of a broader code quality and security program.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parasoft C/C++test
&lt;/h3&gt;

&lt;p&gt;Parasoft provides MISRA C checking integrated with unit testing, code coverage, and requirements traceability. This all-in-one approach is attractive for teams that need to demonstrate compliance across the full V-model development lifecycle. Parasoft generates compliance reports mapped to specific safety standards like ISO 26262 and IEC 62304.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams following V-model development with integrated testing and compliance requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cppcheck (Open Source)
&lt;/h3&gt;

&lt;p&gt;Cppcheck is a free, open-source static analysis tool that includes a MISRA C addon. The addon covers a subset of MISRA C:2012 rules - roughly 100 of the 159 rules. While not comprehensive enough for formal certification, Cppcheck is useful for teams starting their MISRA journey or as a pre-check before running commercial tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Open-source projects, teams evaluating MISRA adoption, or as a supplementary check.&lt;/p&gt;

&lt;h3&gt;
  
  
  LDRA TBvision
&lt;/h3&gt;

&lt;p&gt;LDRA provides end-to-end verification tooling for safety-critical software. TBvision covers MISRA C checking, structural coverage analysis, requirements tracing, and test management. LDRA has deep roots in aerospace (DO-178C) and is qualified as a verification tool under multiple safety standards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Aerospace and defense teams requiring DO-178C tool qualification.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating MISRA Checking into CI/CD
&lt;/h2&gt;

&lt;p&gt;Automated MISRA checking in your CI/CD pipeline catches violations before they reach the main branch. Here is how to set it up effectively:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Establish Your Rule Profile
&lt;/h3&gt;

&lt;p&gt;Not every project needs to comply with all 175 guidelines. Create a configuration file that specifies which rules your project enforces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* misra_config.txt - project MISRA rule selection */
/* All mandatory rules are always enforced */
/* Required rules - enforced with deviation process */
Rule 10.3: enabled
Rule 10.4: enabled
Rule 11.3: enabled
Rule 12.2: enabled
Rule 14.2: enabled
Rule 14.4: enabled
Rule 17.7: enabled

/* Advisory rules - selected subset */
Rule 15.5: enabled
Rule 15.6: enabled
Rule 15.7: enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Add MISRA Checking to Your Build Pipeline
&lt;/h3&gt;

&lt;p&gt;Here is a GitHub Actions example using Cppcheck's MISRA addon as a starting point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/misra-check.yml&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MISRA C Compliance Check&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;**.c'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;**.h'&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;misra-check&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Cppcheck&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;sudo apt-get update&lt;/span&gt;
          &lt;span class="s"&gt;sudo apt-get install -y cppcheck&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run MISRA C check&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;cppcheck \&lt;/span&gt;
            &lt;span class="s"&gt;--addon=misra \&lt;/span&gt;
            &lt;span class="s"&gt;--suppress=missingIncludeSystem \&lt;/span&gt;
            &lt;span class="s"&gt;--error-exitcode=1 \&lt;/span&gt;
            &lt;span class="s"&gt;--inline-suppr \&lt;/span&gt;
            &lt;span class="s"&gt;-I include/ \&lt;/span&gt;
            &lt;span class="s"&gt;src/&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload results&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;failure()&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;misra-violations&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;misra-report.txt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For commercial tools like Polyspace or Helix QAC, the CI integration typically involves a containerized version of the tool running in your pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Polyspace Bug Finder&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;polyspace-bug-finder \&lt;/span&gt;
            &lt;span class="s"&gt;-sources src/ \&lt;/span&gt;
            &lt;span class="s"&gt;-I include/ \&lt;/span&gt;
            &lt;span class="s"&gt;-misra3 mandatory-required \&lt;/span&gt;
            &lt;span class="s"&gt;-results-dir ./polyspace-results&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check for MISRA violations&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;polyspace-report-generator \&lt;/span&gt;
            &lt;span class="s"&gt;-results-dir ./polyspace-results \&lt;/span&gt;
            &lt;span class="s"&gt;-output-format csv \&lt;/span&gt;
            &lt;span class="s"&gt;-report misra-compliance.csv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Gate Merges on MISRA Compliance
&lt;/h3&gt;

&lt;p&gt;Configure your CI to block pull requests that introduce new MISRA violations. Use baseline files to track existing violations separately from new ones - this lets you adopt MISRA incrementally on legacy codebases without requiring a full rewrite before you can enforce the rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Track Deviations in Version Control
&lt;/h3&gt;

&lt;p&gt;Store deviation records alongside the code they apply to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* DEVIATION: Rule 11.3 - Required
 * Justification: Hardware register access requires pointer cast
 *                to volatile uint32_t at fixed memory address.
 * Risk assessment: Address is validated at system startup.
 * Approved by: Safety team review 2026-01-15
 */&lt;/span&gt;
&lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gpio_port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0x40020000U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="cm"&gt;/* cppcheck-suppress misra-c2012-11.3 */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Common MISRA C Adoption Mistakes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Trying to comply with every rule on day one.&lt;/strong&gt; Start with mandatory and required rules. Add advisory rules incrementally as your team builds familiarity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ignoring the deviation process.&lt;/strong&gt; MISRA was designed with deviations in mind. Some rules genuinely cannot be followed in every situation - particularly in low-level hardware interface code. A well-documented deviation is better than a code workaround that introduces its own risks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using only one tool.&lt;/strong&gt; No single static analysis tool catches every MISRA violation. Many teams use two tools - for example, Helix QAC for primary compliance checking and Cppcheck as a fast pre-commit check.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not training the team.&lt;/strong&gt; MISRA compliance is not just a tool configuration. Developers need to understand why each rule exists so they write naturally compliant code instead of fighting the tool output after the fact.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Treating MISRA as a checkbox.&lt;/strong&gt; The goal is safer code, not a clean report. Suppressing findings without understanding them defeats the purpose of the standard.&lt;/p&gt;

&lt;h2&gt;
  
  
  MISRA C:2012 Amendment 4 and Beyond
&lt;/h2&gt;

&lt;p&gt;MISRA C:2012 has been updated through several amendments and technical corrigenda:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Amendment 1 (2016):&lt;/strong&gt; Added guidelines for C11 language features&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amendment 2 (2020):&lt;/strong&gt; Introduced new security-focused rules&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amendment 3 (2023):&lt;/strong&gt; Further security rules and CERT C mapping&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amendment 4 (2025):&lt;/strong&gt; Additional rules covering concurrency and multi-threaded code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The MISRA committee also published MISRA C:2012 Addendum 3 which maps MISRA C rules to CERT C rules, helping teams that need to comply with both standards simultaneously.&lt;/p&gt;

&lt;p&gt;When configuring your tools, make sure you are checking against the latest amendment level your project requires. Tool vendors typically release updates to match new amendments within a few months of publication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;MISRA C:2012 is not just a set of arbitrary restrictions - each rule addresses a real class of bugs that has caused failures in safety-critical systems. The rules around undefined behavior, type safety, pointer usage, and control flow exist because these are the exact areas where C programs fail in dangerous ways.&lt;/p&gt;

&lt;p&gt;If you are starting a new embedded C project in a regulated industry, adopt MISRA C:2012 from the beginning. If you are retrofitting MISRA compliance onto an existing codebase, start with mandatory rules, use baseline files to manage existing violations, and expand coverage incrementally.&lt;/p&gt;

&lt;p&gt;The investment in MISRA compliance pays off not just in passing audits, but in genuinely more reliable software. Code that follows MISRA C is easier to review, easier to test, and far less likely to contain the subtle bugs that only manifest in production under edge-case conditions.&lt;/p&gt;

&lt;p&gt;For teams evaluating &lt;a href="https://dev.to/blog/best-sast-tools"&gt;static analysis tools&lt;/a&gt; that include MISRA checking, the choice between tools often comes down to which safety standard you are targeting, whether you need formal tool qualification, and how the tool fits into your existing build and CI/CD infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is the difference between MISRA C:2004 and MISRA C:2012?
&lt;/h3&gt;

&lt;p&gt;MISRA C:2012 is the successor to MISRA C:2004 and includes significant improvements. It expanded from 142 rules to 175 rules (including directives), added a new 'mandatory' classification level above 'required,' improved the rationale and examples for each rule, and introduced the concept of decidable vs undecidable rules. MISRA C:2012 also added support for C99 language features while retaining C90 compatibility. Teams starting new projects should always use MISRA C:2012 rather than the older 2004 edition.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is MISRA C compliance legally required?
&lt;/h3&gt;

&lt;p&gt;MISRA C compliance is not a law, but it is effectively required in certain industries through functional safety standards. ISO 26262 for automotive software references MISRA C as a recommended coding standard. IEC 62304 for medical device software and DO-178C for avionics software also reference or strongly recommend MISRA-compliant coding practices. In practice, if your product must meet these safety standards, auditors and certification bodies expect MISRA C compliance as evidence of safe coding practices.&lt;/p&gt;

&lt;h3&gt;
  
  
  How many rules are in MISRA C:2012?
&lt;/h3&gt;

&lt;p&gt;MISRA C:2012 contains 175 guidelines split into two types - 16 directives and 159 rules. Directives provide general guidance that may not be fully checkable by static analysis tools, while rules are specific and verifiable. These are further categorized as mandatory (cannot be deviated under any circumstance), required (deviations allowed with documented justification), and advisory (recommended best practices that teams may choose not to follow).&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use dynamic memory allocation with MISRA C?
&lt;/h3&gt;

&lt;p&gt;MISRA C:2012 Directive 4.12 classifies dynamic memory allocation (malloc, calloc, realloc, free) as required to avoid. The concern is that heap allocation introduces risks of memory leaks, fragmentation, and non-deterministic behavior - all dangerous in safety-critical systems. If your project must use dynamic allocation, you need a formal deviation with documented justification, a custom allocator with bounded behavior, or allocation only during initialization with no runtime freeing.&lt;/p&gt;

&lt;h3&gt;
  
  
  What tools can check MISRA C:2012 compliance?
&lt;/h3&gt;

&lt;p&gt;Several commercial and open-source tools check MISRA C:2012 compliance. Leading commercial tools include Polyspace Bug Finder and Code Prover (MathWorks), PC-lint Plus (Gimpel Software), Helix QAC (Perforce), Coverity (Synopsys), Parasoft C/C++test, and LDRA TBvision. For open-source options, Cppcheck provides partial MISRA checking with its addon, and some teams use Clang-Tidy with custom configurations. Commercial tools generally provide higher rule coverage and certified compliance checking required for safety certification audits.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I handle MISRA C deviations?
&lt;/h3&gt;

&lt;p&gt;MISRA C:2012 provides a formal deviation process for required and advisory rules that cannot be followed in specific situations. Each deviation must include the rule being deviated, the justification explaining why compliance is not possible or practical, a risk assessment showing the deviation does not compromise safety, alternative measures taken to mitigate the risk, and approval from a qualified reviewer. Deviations must be documented and tracked. Mandatory rules cannot be deviated under any circumstance.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://aicodereview.cc/blog/misra-c-2012-rules-examples/" rel="noopener noreferrer"&gt;aicodereview.cc&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>ai</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Input vs Output vs Reasoning Tokens Cost - LLM Pricing Explained</title>
      <dc:creator>Rahul Singh</dc:creator>
      <pubDate>Sat, 11 Apr 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/rahulxsingh/input-vs-output-vs-reasoning-tokens-cost-llm-pricing-explained-hi8</link>
      <guid>https://dev.to/rahulxsingh/input-vs-output-vs-reasoning-tokens-cost-llm-pricing-explained-hi8</guid>
      <description>&lt;p&gt;If you have ever checked the pricing page for OpenAI, Anthropic, or Google and wondered why there are three different token prices listed, you are not alone. The distinction between input tokens, output tokens, and reasoning tokens is one of the most misunderstood aspects of LLM pricing - and getting it wrong can mean overspending by 5-10x on your AI workloads.&lt;/p&gt;

&lt;p&gt;This guide breaks down exactly what each token type is, why they cost different amounts, and how to optimize your spending - whether you are building an AI application, running code reviews, or just trying to understand your API bill.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Tokens in LLMs?
&lt;/h2&gt;

&lt;p&gt;Before diving into pricing, let's clarify what tokens actually are. A token is the fundamental unit of text that large language models process. It is not a word, not a character, but something in between.&lt;/p&gt;

&lt;p&gt;On average, one token equals roughly 4 characters or 0.75 words in English. The word "understanding" is two tokens. A line of Python code like &lt;code&gt;def calculate_total(items):&lt;/code&gt; is about 8 tokens.&lt;/p&gt;

&lt;p&gt;Every API call involves two phases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Input processing&lt;/strong&gt; - the model reads your prompt (input tokens)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output generation&lt;/strong&gt; - the model writes its response (output tokens)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some newer models add a third phase:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Reasoning&lt;/strong&gt; - the model thinks through the problem before responding (reasoning tokens)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each phase has different computational costs, which is why providers charge differently for each.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input Tokens - What You Send
&lt;/h2&gt;

&lt;p&gt;Input tokens represent everything you send to the model in your API request. This includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;System prompts&lt;/strong&gt; - instructions that define the model's behavior&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User messages&lt;/strong&gt; - your actual question or request&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context&lt;/strong&gt; - code snippets, documents, conversation history&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Few-shot examples&lt;/strong&gt; - example inputs and outputs you provide&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For AI code review, input tokens typically make up the bulk of your usage. When a tool like &lt;a href="https://dev.to/tools/coderabbit"&gt;CodeRabbit&lt;/a&gt; or &lt;a href="https://dev.to/tools/codeant-ai"&gt;CodeAnt AI&lt;/a&gt; reviews a pull request, it sends the diff, surrounding code context, repository rules, and review instructions as input. A single PR review can easily consume 10,000-50,000 input tokens depending on the size of the change.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Input Tokens Are the Cheapest
&lt;/h3&gt;

&lt;p&gt;Input tokens cost less because the model processes them in parallel using a single forward pass through the neural network. All input tokens are read simultaneously, making this phase computationally efficient. The GPU can process thousands of input tokens in roughly the same time it takes to process a few hundred.&lt;/p&gt;

&lt;h2&gt;
  
  
  Output Tokens - What You Receive
&lt;/h2&gt;

&lt;p&gt;Output tokens are the tokens in the model's response. Every word, code snippet, and explanation the model generates counts as output tokens.&lt;/p&gt;

&lt;p&gt;Output tokens are consistently more expensive than input tokens across every major provider. The ratio varies, but output tokens typically cost &lt;strong&gt;3-4x more&lt;/strong&gt; than input tokens.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Output Tokens Cost More
&lt;/h3&gt;

&lt;p&gt;The reason is fundamental to how LLMs work. During output generation, the model must:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Predict one token at a time (autoregressive generation)&lt;/li&gt;
&lt;li&gt;Run a full forward pass through the entire network for each token&lt;/li&gt;
&lt;li&gt;Maintain the full attention context from all previous tokens&lt;/li&gt;
&lt;li&gt;Store and update KV (key-value) cache for each new token&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This sequential process means generating 1,000 output tokens requires roughly 1,000 separate forward passes, while reading 1,000 input tokens requires just one. The GPU utilization during output generation is also less efficient because it processes one token per step instead of batching thousands.&lt;/p&gt;

&lt;p&gt;This is why a verbose model response is not just annoying - it is literally expensive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reasoning Tokens - The Hidden Cost
&lt;/h2&gt;

&lt;p&gt;Reasoning tokens are the newest and most misunderstood token type. Introduced with OpenAI's o1 model and Anthropic's extended thinking feature, reasoning tokens represent the model's internal chain-of-thought process.&lt;/p&gt;

&lt;p&gt;When you ask a reasoning model to solve a complex problem, it does not jump straight to the answer. Instead, it generates an internal monologue - breaking the problem into steps, considering approaches, checking its work, and then producing the final response.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Reasoning Tokens Work
&lt;/h3&gt;

&lt;p&gt;Here is what happens when you send a request to a reasoning model:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The model reads your input tokens (same as any model)&lt;/li&gt;
&lt;li&gt;The model generates &lt;strong&gt;reasoning tokens&lt;/strong&gt; - internal thinking that you do not see&lt;/li&gt;
&lt;li&gt;The model generates &lt;strong&gt;output tokens&lt;/strong&gt; - the visible response&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The critical detail: &lt;strong&gt;reasoning tokens are billed at the output token rate&lt;/strong&gt; because they require the same expensive sequential generation process. But they are not visible in the API response.&lt;/p&gt;

&lt;p&gt;This means a request that returns a 500-token response might actually consume 3,000 or more total output tokens - 2,500 for reasoning and 500 for the visible answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Models That Use Reasoning Tokens
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Reasoning Type&lt;/th&gt;
&lt;th&gt;Reasoning Visible?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;o1&lt;/td&gt;
&lt;td&gt;OpenAI&lt;/td&gt;
&lt;td&gt;Built-in chain-of-thought&lt;/td&gt;
&lt;td&gt;No (summary only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;o3&lt;/td&gt;
&lt;td&gt;OpenAI&lt;/td&gt;
&lt;td&gt;Built-in chain-of-thought&lt;/td&gt;
&lt;td&gt;No (summary only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;o4-mini&lt;/td&gt;
&lt;td&gt;OpenAI&lt;/td&gt;
&lt;td&gt;Built-in chain-of-thought&lt;/td&gt;
&lt;td&gt;No (summary only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Opus 4.5+&lt;/td&gt;
&lt;td&gt;Anthropic&lt;/td&gt;
&lt;td&gt;Extended thinking&lt;/td&gt;
&lt;td&gt;Yes (thinking blocks)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Sonnet 4.5+&lt;/td&gt;
&lt;td&gt;Anthropic&lt;/td&gt;
&lt;td&gt;Extended thinking&lt;/td&gt;
&lt;td&gt;Yes (thinking blocks)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini 2.5 Pro&lt;/td&gt;
&lt;td&gt;Google&lt;/td&gt;
&lt;td&gt;Thinking mode&lt;/td&gt;
&lt;td&gt;Yes (thought summaries)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One important difference: Anthropic's extended thinking tokens are visible to the developer (returned as &lt;code&gt;thinking&lt;/code&gt; blocks), while OpenAI's reasoning tokens are hidden. Both are billed at output rates.&lt;/p&gt;

&lt;h2&gt;
  
  
  LLM Token Pricing Comparison (March 2026)
&lt;/h2&gt;

&lt;p&gt;Here is the current pricing for major LLM providers. All prices are per million tokens.&lt;/p&gt;

&lt;h3&gt;
  
  
  Standard Models (No Reasoning)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Input (per 1M)&lt;/th&gt;
&lt;th&gt;Output (per 1M)&lt;/th&gt;
&lt;th&gt;Output/Input Ratio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GPT-4o&lt;/td&gt;
&lt;td&gt;$2.50&lt;/td&gt;
&lt;td&gt;$10.00&lt;/td&gt;
&lt;td&gt;4x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-4o-mini&lt;/td&gt;
&lt;td&gt;$0.15&lt;/td&gt;
&lt;td&gt;$0.60&lt;/td&gt;
&lt;td&gt;4x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-4.1&lt;/td&gt;
&lt;td&gt;$2.00&lt;/td&gt;
&lt;td&gt;$8.00&lt;/td&gt;
&lt;td&gt;4x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-4.1-mini&lt;/td&gt;
&lt;td&gt;$0.40&lt;/td&gt;
&lt;td&gt;$1.60&lt;/td&gt;
&lt;td&gt;4x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Opus 4.5&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;td&gt;$25.00&lt;/td&gt;
&lt;td&gt;5x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Sonnet 4.5&lt;/td&gt;
&lt;td&gt;$3.00&lt;/td&gt;
&lt;td&gt;$15.00&lt;/td&gt;
&lt;td&gt;5x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Haiku 4.5&lt;/td&gt;
&lt;td&gt;$1.00&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;td&gt;5x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini 2.5 Pro&lt;/td&gt;
&lt;td&gt;$1.25&lt;/td&gt;
&lt;td&gt;$10.00&lt;/td&gt;
&lt;td&gt;8x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini 2.5 Flash&lt;/td&gt;
&lt;td&gt;$0.30&lt;/td&gt;
&lt;td&gt;$2.50&lt;/td&gt;
&lt;td&gt;8.3x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek V3&lt;/td&gt;
&lt;td&gt;$0.28&lt;/td&gt;
&lt;td&gt;$0.42&lt;/td&gt;
&lt;td&gt;1.5x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Reasoning Models
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Input (per 1M)&lt;/th&gt;
&lt;th&gt;Output (per 1M)&lt;/th&gt;
&lt;th&gt;Reasoning Rate&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;o1&lt;/td&gt;
&lt;td&gt;$15.00&lt;/td&gt;
&lt;td&gt;$60.00&lt;/td&gt;
&lt;td&gt;Same as output&lt;/td&gt;
&lt;td&gt;Most expensive reasoning model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;o3&lt;/td&gt;
&lt;td&gt;$2.00&lt;/td&gt;
&lt;td&gt;$8.00&lt;/td&gt;
&lt;td&gt;Same as output&lt;/td&gt;
&lt;td&gt;Best price-to-reasoning ratio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;o4-mini&lt;/td&gt;
&lt;td&gt;$1.10&lt;/td&gt;
&lt;td&gt;$4.40&lt;/td&gt;
&lt;td&gt;Same as output&lt;/td&gt;
&lt;td&gt;Budget reasoning option&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Sonnet (thinking)&lt;/td&gt;
&lt;td&gt;$3.00&lt;/td&gt;
&lt;td&gt;$15.00&lt;/td&gt;
&lt;td&gt;Same as output&lt;/td&gt;
&lt;td&gt;Extended thinking enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Opus (thinking)&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;td&gt;$25.00&lt;/td&gt;
&lt;td&gt;Same as output&lt;/td&gt;
&lt;td&gt;Extended thinking enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini 2.5 Pro (thinking)&lt;/td&gt;
&lt;td&gt;$1.25&lt;/td&gt;
&lt;td&gt;$10.00&lt;/td&gt;
&lt;td&gt;Same as output&lt;/td&gt;
&lt;td&gt;Thinking mode enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notice that reasoning models do not have a separate per-token rate for reasoning. Instead, reasoning tokens are simply billed as output tokens. The cost impact comes from the volume - a reasoning model might generate 5-10x more total output tokens than a standard model for the same request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Cost Calculations
&lt;/h2&gt;

&lt;p&gt;Let's work through some practical examples to show how token types affect your actual spending.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 1 - Simple Code Review with GPT-4o
&lt;/h3&gt;

&lt;p&gt;You send a 200-line diff for review with a system prompt and code context.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Tokens&lt;/th&gt;
&lt;th&gt;Rate&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;System prompt&lt;/td&gt;
&lt;td&gt;2,000&lt;/td&gt;
&lt;td&gt;$2.50/1M input&lt;/td&gt;
&lt;td&gt;$0.005&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code diff + context&lt;/td&gt;
&lt;td&gt;8,000&lt;/td&gt;
&lt;td&gt;$2.50/1M input&lt;/td&gt;
&lt;td&gt;$0.020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Review response&lt;/td&gt;
&lt;td&gt;1,500&lt;/td&gt;
&lt;td&gt;$10.00/1M output&lt;/td&gt;
&lt;td&gt;$0.015&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;11,500&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.040&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;At this rate, reviewing 100 PRs per month costs about &lt;strong&gt;$4.00&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 2 - Deep Security Review with o3
&lt;/h3&gt;

&lt;p&gt;Same diff, but you want the model to reason through potential security vulnerabilities.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Tokens&lt;/th&gt;
&lt;th&gt;Rate&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;System prompt&lt;/td&gt;
&lt;td&gt;2,000&lt;/td&gt;
&lt;td&gt;$2.00/1M input&lt;/td&gt;
&lt;td&gt;$0.004&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code diff + context&lt;/td&gt;
&lt;td&gt;8,000&lt;/td&gt;
&lt;td&gt;$2.00/1M input&lt;/td&gt;
&lt;td&gt;$0.016&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reasoning tokens (hidden)&lt;/td&gt;
&lt;td&gt;6,000&lt;/td&gt;
&lt;td&gt;$8.00/1M output&lt;/td&gt;
&lt;td&gt;$0.048&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Visible response&lt;/td&gt;
&lt;td&gt;2,000&lt;/td&gt;
&lt;td&gt;$8.00/1M output&lt;/td&gt;
&lt;td&gt;$0.016&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;18,000&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.084&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The reasoning tokens more than doubled the cost compared to a standard model, even though the visible output was similar in length.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 3 - High-Volume Review with GPT-4o-mini
&lt;/h3&gt;

&lt;p&gt;For a team doing 500 PR reviews per month with lighter analysis.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Tokens per Review&lt;/th&gt;
&lt;th&gt;Monthly Total&lt;/th&gt;
&lt;th&gt;Rate&lt;/th&gt;
&lt;th&gt;Monthly Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Input tokens&lt;/td&gt;
&lt;td&gt;8,000&lt;/td&gt;
&lt;td&gt;4,000,000&lt;/td&gt;
&lt;td&gt;$0.15/1M&lt;/td&gt;
&lt;td&gt;$0.60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output tokens&lt;/td&gt;
&lt;td&gt;1,000&lt;/td&gt;
&lt;td&gt;500,000&lt;/td&gt;
&lt;td&gt;$0.60/1M&lt;/td&gt;
&lt;td&gt;$0.30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.90/month&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That is less than a dollar per month for 500 code reviews. This is why smaller models are so attractive for high-volume, lower-complexity tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Output-to-Input Ratio Matters
&lt;/h2&gt;

&lt;p&gt;The output-to-input cost ratio varies significantly across providers, and understanding this ratio is crucial for cost optimization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google's Gemini models have the highest ratio&lt;/strong&gt; at 8x, meaning output tokens cost eight times more than input tokens. If your use case is output-heavy (generating long code, documentation, or detailed reviews), Gemini becomes comparatively more expensive on the output side despite having competitive input prices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DeepSeek has the lowest ratio&lt;/strong&gt; at just 1.5x, making it the most balanced option for output-heavy workloads. However, DeepSeek's overall quality for code review tasks may not match GPT-4o or Claude for certain languages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OpenAI and Anthropic sit at 4-5x&lt;/strong&gt;, which is the most common range across the industry.&lt;/p&gt;

&lt;p&gt;The practical takeaway: if you can keep your outputs short and your inputs lean, you will save the most money with high-ratio providers. If your task requires long outputs, a lower-ratio provider might be cheaper overall even if its base rates are higher.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prompt Caching - The Biggest Cost Saver
&lt;/h2&gt;

&lt;p&gt;Prompt caching is the single most effective way to reduce LLM API costs, especially for AI code review workloads where the same system prompt and repository context are sent with every request.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Prompt Caching Works
&lt;/h3&gt;

&lt;p&gt;Instead of reprocessing the same prompt prefix on every request, the provider stores it in GPU memory. Subsequent requests that share the same prefix get a significant discount on those cached input tokens.&lt;/p&gt;

&lt;h3&gt;
  
  
  Caching Pricing by Provider
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Cache Write Cost&lt;/th&gt;
&lt;th&gt;Cache Read Cost&lt;/th&gt;
&lt;th&gt;Cache Duration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Anthropic&lt;/td&gt;
&lt;td&gt;1.25x base input&lt;/td&gt;
&lt;td&gt;0.1x base input&lt;/td&gt;
&lt;td&gt;5 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anthropic (extended)&lt;/td&gt;
&lt;td&gt;2x base input&lt;/td&gt;
&lt;td&gt;0.1x base input&lt;/td&gt;
&lt;td&gt;1 hour&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenAI&lt;/td&gt;
&lt;td&gt;1x base input (automatic)&lt;/td&gt;
&lt;td&gt;0.5x base input&lt;/td&gt;
&lt;td&gt;Up to 1 hour&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google&lt;/td&gt;
&lt;td&gt;1x base input&lt;/td&gt;
&lt;td&gt;0.25x base input&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Anthropic's caching is the most aggressive - a cache read costs just 10% of the normal input rate. For Claude Sonnet at $3/1M input tokens, cached reads cost just $0.30/1M. The 1.25x write overhead pays for itself after a single cache hit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Caching Example for Code Review
&lt;/h3&gt;

&lt;p&gt;Suppose your AI code review tool uses a 3,000-token system prompt with every review. Over 100 reviews:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without caching (Claude Sonnet):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3,000 tokens x 100 reviews = 300,000 input tokens&lt;/li&gt;
&lt;li&gt;Cost: 300,000 / 1M x $3.00 = &lt;strong&gt;$0.90&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;With caching (Claude Sonnet):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First request (cache write): 3,000 tokens x $3.75/1M = $0.011&lt;/li&gt;
&lt;li&gt;99 cached requests: 3,000 x 99 = 297,000 tokens x $0.30/1M = $0.089&lt;/li&gt;
&lt;li&gt;Total: &lt;strong&gt;$0.10&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is an &lt;strong&gt;89% reduction&lt;/strong&gt; just from caching the system prompt. In practice, you can also cache repository-level context, coding standards, and review rules for even greater savings.&lt;/p&gt;

&lt;h2&gt;
  
  
  How AI Code Review Tools Handle Token Costs
&lt;/h2&gt;

&lt;p&gt;Understanding token economics explains many of the design decisions behind modern &lt;a href="https://dev.to/blog/best-ai-code-review-tools"&gt;AI code review tools&lt;/a&gt;. Here is how the major tools manage costs:&lt;/p&gt;

&lt;h3&gt;
  
  
  Diff-Based Analysis
&lt;/h3&gt;

&lt;p&gt;Tools like &lt;a href="https://dev.to/tools/coderabbit"&gt;CodeRabbit&lt;/a&gt;, &lt;a href="https://dev.to/tools/codeant-ai"&gt;CodeAnt AI&lt;/a&gt;, and &lt;a href="https://dev.to/tools/sourcery"&gt;Sourcery&lt;/a&gt; only send the changed code (the diff) rather than entire files. This dramatically reduces input tokens. A 10-line change in a 500-line file uses roughly 95% fewer input tokens than sending the whole file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Model Routing
&lt;/h3&gt;

&lt;p&gt;Sophisticated tools route different types of analysis to different models:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Style and formatting checks&lt;/strong&gt; go to cheap, fast models like GPT-4o-mini or Gemini Flash&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logic and bug detection&lt;/strong&gt; go to mid-tier models like GPT-4o or Claude Sonnet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security vulnerability analysis&lt;/strong&gt; may use reasoning models like o3 for deeper analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This tiered approach can reduce costs by 60-80% compared to using a single premium model for everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prompt Caching for Repository Context
&lt;/h3&gt;

&lt;p&gt;When a code review tool indexes your repository, it builds a context document with your coding standards, common patterns, and project structure. This context is cached and reused across every PR review, saving thousands of input tokens per request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flat Pricing Abstraction
&lt;/h3&gt;

&lt;p&gt;Most &lt;a href="https://dev.to/blog/best-ai-code-review-tools"&gt;AI code review tools&lt;/a&gt; charge a flat per-user monthly fee rather than passing through token costs directly. This means the tool vendor absorbs the token cost risk and optimizes internally. Tools like CodeRabbit ($15/user/month) and CodeAnt AI (free for public repos) handle all the token math behind the scenes.&lt;/p&gt;

&lt;h2&gt;
  
  
  8 Strategies to Optimize Your LLM Token Costs
&lt;/h2&gt;

&lt;p&gt;Whether you are building your own AI-powered tool or managing API costs directly, these strategies will help you spend less without sacrificing quality.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Use Prompt Caching Aggressively
&lt;/h3&gt;

&lt;p&gt;Put your longest, most stable content at the beginning of your prompt. System instructions, few-shot examples, and reference documents are prime candidates for caching. Structure prompts so the cached prefix is reused across as many requests as possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Choose the Right Model for the Task
&lt;/h3&gt;

&lt;p&gt;Do not use o3 or Claude Opus for tasks that GPT-4o-mini can handle. Create a model routing strategy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tier 1 (cheap):&lt;/strong&gt; Formatting, linting, simple classification - GPT-4o-mini, Gemini Flash&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier 2 (balanced):&lt;/strong&gt; Code review, bug detection, summarization - GPT-4o, Claude Sonnet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier 3 (premium):&lt;/strong&gt; Security analysis, architecture review, complex reasoning - o3, Claude Opus&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Trim Your Input Context
&lt;/h3&gt;

&lt;p&gt;Every unnecessary token in your prompt costs money. Remove:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redundant instructions&lt;/li&gt;
&lt;li&gt;Overly verbose few-shot examples&lt;/li&gt;
&lt;li&gt;Code that is not relevant to the current task&lt;/li&gt;
&lt;li&gt;Conversation history beyond what is needed for context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For code review, send only the diff and immediately surrounding lines rather than entire files.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Limit Output Length
&lt;/h3&gt;

&lt;p&gt;Set &lt;code&gt;max_tokens&lt;/code&gt; to prevent the model from generating unnecessarily long responses. If you need a yes/no classification, cap the output at 10 tokens. If you need a code review summary, 500-1,000 tokens is usually sufficient.&lt;/p&gt;

&lt;p&gt;This is especially important with reasoning models where unconstrained thinking budgets can generate thousands of expensive reasoning tokens.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Use Batch APIs for Non-Urgent Work
&lt;/h3&gt;

&lt;p&gt;OpenAI and Anthropic both offer batch processing APIs with significant discounts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI Batch API:&lt;/strong&gt; 50% discount on all models&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anthropic Message Batches:&lt;/strong&gt; 50% discount, results within 24 hours&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your code reviews do not need to be instant (for example, nightly security scans), batch processing cuts your costs in half.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Monitor and Set Spending Limits
&lt;/h3&gt;

&lt;p&gt;Track your token usage by model and endpoint. Set daily and monthly spending limits to avoid surprise bills. Most providers offer usage dashboards and API-level budget controls.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Compress Code Context Intelligently
&lt;/h3&gt;

&lt;p&gt;Instead of sending raw source code, consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sending AST (Abstract Syntax Tree) representations which are more token-efficient&lt;/li&gt;
&lt;li&gt;Using code summaries for files that provide context but are not being reviewed&lt;/li&gt;
&lt;li&gt;Stripping comments and whitespace from context files (but not from the code being reviewed)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8. Cache and Reuse Responses
&lt;/h3&gt;

&lt;p&gt;If multiple developers open PRs that modify similar code, cache the review analysis for shared components. This avoids paying for the same analysis twice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Token Costs for Popular AI Tasks
&lt;/h2&gt;

&lt;p&gt;To put token pricing in broader perspective, here is what common AI-powered developer tasks cost using GPT-4o pricing ($2.50 input / $10.00 output per million tokens):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Input Tokens&lt;/th&gt;
&lt;th&gt;Output Tokens&lt;/th&gt;
&lt;th&gt;Cost per Task&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PR code review (small)&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;td&gt;1,000&lt;/td&gt;
&lt;td&gt;$0.023&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PR code review (large)&lt;/td&gt;
&lt;td&gt;30,000&lt;/td&gt;
&lt;td&gt;3,000&lt;/td&gt;
&lt;td&gt;$0.105&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security vulnerability scan&lt;/td&gt;
&lt;td&gt;20,000&lt;/td&gt;
&lt;td&gt;2,000&lt;/td&gt;
&lt;td&gt;$0.070&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code documentation generation&lt;/td&gt;
&lt;td&gt;3,000&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;td&gt;$0.058&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bug explanation and fix&lt;/td&gt;
&lt;td&gt;4,000&lt;/td&gt;
&lt;td&gt;2,000&lt;/td&gt;
&lt;td&gt;$0.030&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test case generation&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;td&gt;8,000&lt;/td&gt;
&lt;td&gt;$0.093&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Architecture review&lt;/td&gt;
&lt;td&gt;50,000&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;td&gt;$0.175&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These costs are per individual task. At scale, they add up - but they are remarkably cheap compared to the developer time they save.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Future of Token Pricing
&lt;/h2&gt;

&lt;p&gt;Token prices have dropped roughly 80% from 2024 to 2026, and the trend shows no signs of slowing. Several factors are driving costs down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hardware improvements&lt;/strong&gt; - newer GPU architectures (NVIDIA Blackwell, AMD MI400) are more efficient&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model distillation&lt;/strong&gt; - smaller models trained on outputs from larger models close the quality gap at lower cost&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inference optimization&lt;/strong&gt; - techniques like speculative decoding, quantization, and better KV cache management reduce compute per token&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competition&lt;/strong&gt; - DeepSeek, Mistral, and open-source models keep pressure on pricing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For AI code review tools, this means the cost of running comprehensive analysis on every PR is approaching near-zero. The limiting factor is shifting from cost to quality - which model provides the most accurate, lowest-false-positive reviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  How This Affects Your Choice of AI Code Review Tool
&lt;/h2&gt;

&lt;p&gt;When evaluating &lt;a href="https://dev.to/blog/best-ai-code-review-tools"&gt;AI code review tools&lt;/a&gt;, understanding token economics helps you assess whether a tool's pricing is fair:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tools charging $15-30/user/month&lt;/strong&gt; likely use mid-tier models with caching, which is sustainable and cost-effective&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools offering unlimited free tiers&lt;/strong&gt; are either using very cheap models, heavily rate-limiting, or subsidizing costs with venture capital&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-hosted tools&lt;/strong&gt; like &lt;a href="https://dev.to/tools/sonarqube"&gt;SonarQube&lt;/a&gt; or &lt;a href="https://dev.to/tools/semgrep"&gt;Semgrep&lt;/a&gt; avoid token costs entirely but require infrastructure investment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best value typically comes from tools that intelligently route between model tiers - using cheap models for simple checks and premium models only when the complexity warrants it. &lt;a href="https://dev.to/tools/codeant-ai"&gt;CodeAnt AI&lt;/a&gt; and &lt;a href="https://dev.to/tools/coderabbit"&gt;CodeRabbit&lt;/a&gt; both take this approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Input tokens&lt;/strong&gt; are cheapest because the model processes them in parallel&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output tokens&lt;/strong&gt; cost 3-8x more because they require sequential generation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reasoning tokens&lt;/strong&gt; are billed as output tokens and can multiply your costs 3-10x with no visible output increase&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt caching&lt;/strong&gt; can reduce costs by up to 90% for repeated prompts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model routing&lt;/strong&gt; - using cheap models for simple tasks - is the most impactful optimization strategy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch APIs&lt;/strong&gt; offer 50% discounts for non-urgent workloads&lt;/li&gt;
&lt;li&gt;For AI code review, token costs are now low enough that comprehensive analysis on every PR is economically viable for teams of any size&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding these fundamentals puts you in control of your AI spending rather than being surprised by your monthly bill. Whether you are using AI APIs directly or evaluating managed tools, knowing what drives token costs helps you make smarter decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why do output tokens cost more than input tokens?
&lt;/h3&gt;

&lt;p&gt;Output tokens cost 2-6x more than input tokens because generating text is far more compute-intensive than reading it. During input processing, the model runs one forward pass over all tokens in parallel. During output generation, the model must run a separate forward pass for every single token, predicting one token at a time while maintaining the full context. This sequential, autoregressive process requires significantly more GPU time and memory bandwidth per token.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are reasoning tokens and how are they billed?
&lt;/h3&gt;

&lt;p&gt;Reasoning tokens are internal chain-of-thought tokens generated by models like OpenAI o1, o3, and Claude with extended thinking. These tokens represent the model's step-by-step problem-solving process. They are billed at the output token rate because they require the same sequential generation process. Reasoning tokens are not visible in the API response but still consume your token budget and context window. A 500-token visible response may use 2,000 or more total tokens when reasoning is included.&lt;/p&gt;

&lt;h3&gt;
  
  
  How can I reduce LLM API costs without losing quality?
&lt;/h3&gt;

&lt;p&gt;The most effective strategies are prompt caching (up to 90% savings on repeated prompts), using smaller models for simple tasks and reserving expensive models for complex ones, trimming unnecessary context from prompts, batching requests during off-peak hours for 50% discounts, and setting maximum token limits on output. For AI code review, focusing reviews on changed files only rather than entire repositories dramatically reduces input token usage.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does prompt caching work and when should I use it?
&lt;/h3&gt;

&lt;p&gt;Prompt caching stores frequently used prompt prefixes so they do not need to be reprocessed on every request. Anthropic charges 0.1x the base input rate for cache reads and 1.25x for 5-minute cache writes. OpenAI offers automatic caching at 0.5x the input rate. You should use caching whenever you send the same system prompt, code context, or instructions repeatedly - which is exactly how AI code review tools work when analyzing multiple PRs against the same codebase rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which LLM model offers the best value for AI code review?
&lt;/h3&gt;

&lt;p&gt;For most AI code review use cases, GPT-4.1 at $2/$8 per million tokens or Claude Sonnet at $3/$15 offer the best balance of quality and cost. If you need deep reasoning for complex security analysis, o3 at $2/$8 with reasoning tokens is more cost-effective than o1. For high-volume linting and style checks, Gemini 2.5 Flash at $0.30/$2.50 or GPT-4o-mini at $0.15/$0.60 are the most economical choices.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do AI code review tools manage token costs internally?
&lt;/h3&gt;

&lt;p&gt;AI code review tools use several strategies to keep costs manageable. They use diff-based analysis to only send changed code rather than entire files, employ prompt caching for system instructions and repository context, route simple checks to cheaper models while using premium models for security analysis, and batch multiple file reviews where possible. Tools like CodeRabbit and CodeAnt AI abstract this complexity so you pay a flat per-user fee instead of worrying about token math.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://aicodereview.cc/blog/input-vs-output-vs-reasoning-tokens-cost/" rel="noopener noreferrer"&gt;aicodereview.cc&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>ai</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Fake SOC 2 and ISO 27001 Certifications Are Spreading Across Dev Tools</title>
      <dc:creator>Rahul Singh</dc:creator>
      <pubDate>Sat, 11 Apr 2026 10:00:00 +0000</pubDate>
      <link>https://dev.to/rahulxsingh/fake-soc-2-and-iso-27001-certifications-are-spreading-across-dev-tools-48f9</link>
      <guid>https://dev.to/rahulxsingh/fake-soc-2-and-iso-27001-certifications-are-spreading-across-dev-tools-48f9</guid>
      <description>&lt;p&gt;A detailed investigation published on Substack has alleged that Delve, a compliance automation platform, systematically manufactured false SOC 2 and ISO 27001 certifications for its clients. If the allegations hold up, it represents one of the largest compliance fraud operations in the startup ecosystem.&lt;/p&gt;

&lt;p&gt;For developers and engineering teams that rely on compliance certifications when evaluating tools, this is a wake-up call.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happened with Delve
&lt;/h2&gt;

&lt;p&gt;According to the investigation, Delve operated by pre-populating audit evidence, generating test procedures and conclusions internally, and then routing the finished package to auditing firms that would rubber-stamp the results without conducting independent verification.&lt;/p&gt;

&lt;p&gt;The key allegations include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fabricated audit evidence&lt;/strong&gt; - Delve's platform allegedly generated compliance artifacts and pre-filled audit conclusions rather than requiring clients to demonstrate actual security controls&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-independent auditors&lt;/strong&gt; - The auditing firms used were reportedly Indian certification mills operating through US shell entities, violating AICPA independence requirements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Misleading marketing&lt;/strong&gt; - Claims about "US-based auditors" allegedly masked the actual audit process, and trust pages displayed security badges before any compliance work had begun&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wide impact&lt;/strong&gt; - Multiple companies including venture-backed startups and at least one NASDAQ-listed firm reportedly received these certifications, collectively handling millions of customer records&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The auditing firms named in the investigation include Accorp, Gradient Certification, Glocert, and DKPC - described as accepting pre-written conclusions rather than performing genuine independent audits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters for Developer Tools
&lt;/h2&gt;

&lt;p&gt;If you evaluate code review tools, security scanners, or any SaaS platform, you have probably looked at compliance certifications as a trust signal. SOC 2 and ISO 27001 badges appear on nearly every tool's security page.&lt;/p&gt;

&lt;p&gt;Here is the problem: &lt;strong&gt;a badge is not proof of anything&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A legitimate SOC 2 Type II report means an independent auditor observed a company's security controls operating effectively over 6 to 12 months. It covers access controls, encryption, incident response, change management, and more. When done properly, it is a meaningful signal.&lt;/p&gt;

&lt;p&gt;But when the audit process itself is compromised, the certification becomes theater. A tool could display a SOC 2 badge while having:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No real access controls&lt;/li&gt;
&lt;li&gt;Unencrypted data at rest&lt;/li&gt;
&lt;li&gt;No incident response plan&lt;/li&gt;
&lt;li&gt;No change management process&lt;/li&gt;
&lt;li&gt;No employee security training&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is particularly dangerous for tools that touch your source code. Code review platforms, static analysis tools, and AI coding assistants often require read access to your repositories. If their security posture is fabricated, your code is exposed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Compliance Automation Problem
&lt;/h2&gt;

&lt;p&gt;Delve is not the only compliance automation platform. The market includes Vanta, Drata, Secureframe, Thoropass, and others. These tools promise to streamline compliance by automating evidence collection, monitoring controls, and connecting companies with auditors.&lt;/p&gt;

&lt;p&gt;The legitimate ones add real value. Automating evidence collection for a team that actually has security controls in place saves hundreds of hours.&lt;/p&gt;

&lt;p&gt;The risk emerges when automation replaces implementation. When a platform generates the evidence itself rather than collecting evidence of real controls, the entire audit becomes a fiction. The company gets a certificate. The auditor gets paid. The customers get nothing.&lt;/p&gt;

&lt;p&gt;This is not a problem with compliance automation as a concept. It is a problem with specific actors exploiting the gap between what a certification implies and what it actually verifies.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Actually Verify a Tool's Security Posture
&lt;/h2&gt;

&lt;p&gt;If you are evaluating developer tools - especially ones that access your code - here is how to go beyond the badge:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Request the Full SOC 2 Type II Report
&lt;/h3&gt;

&lt;p&gt;Any legitimate vendor will share their SOC 2 report under NDA. If they refuse or only offer a "summary," that is a red flag. The full report should include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The auditor's opinion letter&lt;/li&gt;
&lt;li&gt;A description of the system and its boundaries&lt;/li&gt;
&lt;li&gt;The specific controls tested&lt;/li&gt;
&lt;li&gt;The test results, including any exceptions or failures&lt;/li&gt;
&lt;li&gt;The observation period (should be at least 6 months for Type II)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Verify the Auditing Firm
&lt;/h3&gt;

&lt;p&gt;Check if the auditing firm is a licensed CPA firm registered with the AICPA. Look them up on the AICPA's firm directory. A legitimate SOC 2 audit must be performed by a CPA firm. If you have never heard of the firm and cannot find them in the directory, investigate further.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Look for Type II Over Type I
&lt;/h3&gt;

&lt;p&gt;SOC 2 Type I is a point-in-time snapshot - it says "the controls were designed properly on this date." Type II says "the controls operated effectively over this period." Type II is significantly more meaningful because it requires sustained compliance, not just a one-day performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Check for Exceptions in the Report
&lt;/h3&gt;

&lt;p&gt;A clean SOC 2 report with zero exceptions across every control is actually somewhat unusual and could indicate a superficial audit. Real audits often find minor exceptions that the company has remediated. The presence of exceptions (with remediations) can actually indicate a more thorough audit.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Evaluate Security Independently
&lt;/h3&gt;

&lt;p&gt;Compliance certifications should be one data point, not the entire evaluation. Also consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security documentation&lt;/strong&gt; - Does the vendor publish a security whitepaper or maintain a detailed security page with specifics, not just badges?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vulnerability disclosure program&lt;/strong&gt; - Do they have a responsible disclosure policy or bug bounty program?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Incident history&lt;/strong&gt; - How have they handled past security incidents? Transparency matters more than a clean record.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data handling&lt;/strong&gt; - Where is your code processed and stored? Is it used for training? What is the retention policy?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access controls&lt;/strong&gt; - What permissions does the tool actually need? Does it follow least-privilege principles?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What This Means for the Dev Tools Ecosystem
&lt;/h2&gt;

&lt;p&gt;The Delve allegations highlight a systemic vulnerability in how the software industry evaluates trust. We have collectively outsourced security evaluation to certifications, and those certifications are only as good as the audit behind them.&lt;/p&gt;

&lt;p&gt;For dev tool vendors, the lesson is straightforward: invest in actual security, not just the appearance of security. A compromised certification is a ticking time bomb - when it unravels, the reputational damage is catastrophic.&lt;/p&gt;

&lt;p&gt;For developers and engineering leads evaluating tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Do not treat compliance badges as proof.&lt;/strong&gt; They are a starting point for investigation, not a conclusion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read the actual reports.&lt;/strong&gt; SOC 2 reports exist to be read, not just referenced.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify the auditor.&lt;/strong&gt; Five minutes of checking the auditing firm's credentials can save you from trusting a rubber-stamped report.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluate security holistically.&lt;/strong&gt; How a company responds to security questions tells you more than what badges they display.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tools that handle your source code deserve the same scrutiny you would give to any critical infrastructure dependency. A compliance badge should open the conversation, not close it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;This is not just about Delve. The compliance automation industry has grown rapidly, and the incentive structure is fragile. Companies want certifications fast and cheap. Platforms compete on speed and price. Auditors face pressure to approve.&lt;/p&gt;

&lt;p&gt;When the incentives all point toward faster and cheaper certifications, corners get cut. The Delve investigation may be the first major public exposure, but it is unlikely to be the last.&lt;/p&gt;

&lt;p&gt;As developers, we are in a unique position. We understand systems, trust boundaries, and the difference between security theater and actual security. Apply that same rigor to the tools you choose to trust with your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is SOC 2 compliance?
&lt;/h3&gt;

&lt;p&gt;SOC 2 is a security framework developed by the AICPA that evaluates how a company handles customer data across five trust principles - security, availability, processing integrity, confidentiality, and privacy. An independent auditor must verify controls before issuing a SOC 2 report.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can a SOC 2 report be faked?
&lt;/h3&gt;

&lt;p&gt;Yes. As the Delve investigation shows, some compliance automation platforms allegedly pre-populate audit evidence, use non-independent auditors, and generate rubber-stamped reports. Without proper verification, a SOC 2 badge on a website can be meaningless.&lt;/p&gt;

&lt;h3&gt;
  
  
  How can I verify if a tool's SOC 2 certification is real?
&lt;/h3&gt;

&lt;p&gt;Ask the vendor for their full SOC 2 Type II report (not just a badge). Check the auditing firm's credentials on the AICPA website. Look for a Type II report that covers at least 6 months of observation, and verify the auditor is a licensed CPA firm with no conflicts of interest.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the difference between SOC 2 Type I and Type II?
&lt;/h3&gt;

&lt;p&gt;Type I evaluates whether security controls are properly designed at a single point in time. Type II tests whether those controls actually operated effectively over a period of 6 to 12 months. Type II is significantly more rigorous and trustworthy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I stop trusting compliance certifications entirely?
&lt;/h3&gt;

&lt;p&gt;No. Legitimate SOC 2 and ISO 27001 certifications remain valuable signals. But they should be one input among many. Verify the auditor, read the actual report, and evaluate the vendor's security practices independently rather than relying on a badge alone.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://aicodereview.cc/blog/fake-compliance-certifications-dev-tools/" rel="noopener noreferrer"&gt;aicodereview.cc&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>ai</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Export Azure DevOps Data to Excel (6 Methods, 2026)</title>
      <dc:creator>Rahul Singh</dc:creator>
      <pubDate>Sat, 11 Apr 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/rahulxsingh/how-to-export-azure-devops-data-to-excel-6-methods-2026-20c2</link>
      <guid>https://dev.to/rahulxsingh/how-to-export-azure-devops-data-to-excel-6-methods-2026-20c2</guid>
      <description>&lt;h2&gt;
  
  
  Why export Azure DevOps data to Excel
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Teams export Azure DevOps data to Excel for reporting, audits, stakeholder presentations, offline analysis, and data migration.&lt;/strong&gt; While Azure DevOps has built-in dashboards and Analytics views, Excel remains the tool that everyone on a team - including project managers, QA leads, and executives who never log into Azure DevOps - already knows how to use.&lt;/p&gt;

&lt;p&gt;Common scenarios where exporting to Excel makes sense:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sprint reports&lt;/strong&gt; - pulling work item data for burndown charts and velocity calculations outside of Azure DevOps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance audits&lt;/strong&gt; - exporting code review history, test results, and pipeline logs for SOC 2 or ISO 27001 documentation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stakeholder updates&lt;/strong&gt; - creating filtered views of project status that non-technical team members can read&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data migration&lt;/strong&gt; - moving work items between Azure DevOps organizations or to another platform&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom analysis&lt;/strong&gt; - running pivot tables, VLOOKUP formulas, or statistical analysis that Azure DevOps dashboards do not support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offline access&lt;/strong&gt; - having a snapshot of project data when internet access is unavailable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guide covers six methods to get data out of Azure DevOps and into Excel, ranked from simplest to most powerful. Each method has different strengths depending on what type of data you need and how much automation you want.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 1 - Built-in Open in Excel (work items)
&lt;/h2&gt;

&lt;p&gt;The fastest way to export Azure DevOps work items to Excel is the built-in Office Integration feature. This creates a live, bidirectional connection between Excel and Azure DevOps - meaning you can not only read data but also edit work items directly in Excel and publish changes back.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before using this method, you need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Excel 2016 or later&lt;/strong&gt; installed on your machine (Excel for Microsoft 365 recommended)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure DevOps Office Integration plugin&lt;/strong&gt; - included with Visual Studio 2019+, or available as a standalone download from the Visual Studio Marketplace&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permission&lt;/strong&gt; to read work items in the Azure DevOps project&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step-by-step process
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Step 1 - Create or open a work item query&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Navigate to your Azure DevOps project. Go to &lt;strong&gt;Boards &amp;gt; Queries&lt;/strong&gt;. Either open an existing saved query or create a new one. For example, to export all user stories in the current sprint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;Work&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt; &lt;span class="k"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;User&lt;/span&gt; &lt;span class="n"&gt;Story&lt;/span&gt;
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="k"&gt;State&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Removed&lt;/span&gt;
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;Iteration&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;CurrentIteration&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure the query returns the columns you want in Excel. Click &lt;strong&gt;Column Options&lt;/strong&gt; to add or remove fields like Story Points, Assigned To, Area Path, Tags, and any custom fields your team uses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2 - Click Open in Excel&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With the query results displayed, click the &lt;strong&gt;Open in Excel&lt;/strong&gt; button in the toolbar. This button appears at the top of the query results page. If you do not see it, confirm the Office Integration plugin is installed.&lt;/p&gt;

&lt;p&gt;Azure DevOps will generate an &lt;code&gt;.xlsx&lt;/code&gt; file and open it in Excel with the Team plugin connected. The spreadsheet will contain one row per work item with all the columns from your query.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 - Work with the data in Excel&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once the data is in Excel, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sort and filter using standard Excel features&lt;/li&gt;
&lt;li&gt;Create pivot tables from the work item data&lt;/li&gt;
&lt;li&gt;Add conditional formatting to highlight blocked items or overdue tasks&lt;/li&gt;
&lt;li&gt;Use formulas to calculate custom metrics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 4 - Refresh data (optional)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because this is a live connection, you can click &lt;strong&gt;Refresh&lt;/strong&gt; in the Team ribbon tab to pull the latest data from Azure DevOps at any time. This is useful for recurring reports where you want to update the numbers without re-exporting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations of the built-in method
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Only works on Windows (the Office Integration plugin does not support macOS)&lt;/li&gt;
&lt;li&gt;Limited to work items - you cannot export pipeline data, test results, or repository statistics this way&lt;/li&gt;
&lt;li&gt;Maximum of 50,000 work items per query&lt;/li&gt;
&lt;li&gt;Requires the desktop Excel application - Excel for the web does not support the plugin&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Method 2 - CSV export from the web UI
&lt;/h2&gt;

&lt;p&gt;If you are on macOS or Linux, or simply do not want to install the Office Integration plugin, the CSV export is the next simplest option.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step-by-step process
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Step 1 - Run your work item query&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Go to &lt;strong&gt;Boards &amp;gt; Queries&lt;/strong&gt; in the Azure DevOps web portal. Open or create a query with the columns and filters you need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2 - Export to CSV&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Click the three-dot menu (more actions) at the top right of the query results. Select &lt;strong&gt;Export to CSV&lt;/strong&gt;. Azure DevOps will generate a &lt;code&gt;.csv&lt;/code&gt; file and download it to your browser's default download location.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 - Open in Excel&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open the CSV file in Excel. If your data contains special characters or non-English text, use Excel's &lt;strong&gt;Data &amp;gt; From Text/CSV&lt;/strong&gt; import wizard and set the encoding to UTF-8 to avoid garbled characters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4 - Format and save as .xlsx&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once imported, format the data as needed and save as an &lt;code&gt;.xlsx&lt;/code&gt; file to preserve formatting, formulas, and multiple sheets.&lt;/p&gt;

&lt;h3&gt;
  
  
  CSV export tips
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Column selection matters&lt;/strong&gt; - only columns visible in the query results will appear in the CSV. Add all the fields you need before exporting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTML fields get messy&lt;/strong&gt; - rich text fields like Description and Acceptance Criteria export as raw HTML in CSV. You may need to clean these up in Excel or strip HTML tags with a formula like &lt;code&gt;=CLEAN(SUBSTITUTE(A1,"&amp;lt;br&amp;gt;",CHAR(10)))&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dates may need reformatting&lt;/strong&gt; - depending on your locale, date fields might import as text. Use Excel's &lt;strong&gt;Text to Columns&lt;/strong&gt; or &lt;code&gt;DATEVALUE()&lt;/code&gt; function to convert them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Method 3 - REST API export with PowerShell or Python
&lt;/h2&gt;

&lt;p&gt;When you need data that the built-in export does not cover - pipeline runs, pull request details, code review comments, build logs, or any data beyond work items - the Azure DevOps REST API is the way to go.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exporting work items with PowerShell
&lt;/h3&gt;

&lt;p&gt;This script runs a WIQL query and exports the results to a CSV file that Excel can open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Configuration&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$org&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-organization"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$project&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-project"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$pat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-personal-access-token"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$outputFile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"work-items-export.csv"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Create auth header&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$base64Auth&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Convert&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;ToBase64String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Text.Encoding&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;ASCII.GetBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;":&lt;/span&gt;&lt;span class="nv"&gt;$pat&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$headers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nx"&gt;Authorization&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Basic &lt;/span&gt;&lt;span class="nv"&gt;$base64Auth&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"Content-Type"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"application/json"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Step 1 - Run a WIQL query to get work item IDs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$wiqlBody&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = '&lt;/span&gt;&lt;span class="nv"&gt;$project&lt;/span&gt;&lt;span class="s2"&gt;' AND [System.WorkItemType] = 'User Story' AND [System.State] &amp;lt;&amp;gt; 'Removed' ORDER BY [System.Id]"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ConvertTo-Json&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nv"&gt;$wiqlUrl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://dev.azure.com/&lt;/span&gt;&lt;span class="nv"&gt;$org&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$project&lt;/span&gt;&lt;span class="s2"&gt;/_apis/wit/wiql?api-version=7.1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$wiqlResult&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Invoke-RestMethod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$wiqlUrl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Headers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$headers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Body&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$wiqlBody&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Step 2 - Fetch full work item details in batches of 200&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$ids&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$wiqlResult&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;workItems&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$allWorkItems&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@()&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kr"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-lt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ids&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$batch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ids&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;Min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;199&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ids&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$idsParam&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$batch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-join&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;","&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$detailUrl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://dev.azure.com/&lt;/span&gt;&lt;span class="nv"&gt;$org&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$project&lt;/span&gt;&lt;span class="s2"&gt;/_apis/wit/workitems?ids=&lt;/span&gt;&lt;span class="nv"&gt;$idsParam&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;&lt;/span&gt;&lt;span class="se"&gt;`$&lt;/span&gt;&lt;span class="s2"&gt;expand=fields&amp;amp;api-version=7.1"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$details&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Invoke-RestMethod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$detailUrl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Get&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Headers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$headers&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$allWorkItems&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$details&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Step 3 - Convert to flat objects and export as CSV&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$allWorkItems&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ForEach-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PSCustomObject&lt;/span&gt;&lt;span class="p"&gt;]@{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;Title&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'System.Title'&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'System.State'&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;AssignedTo&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'System.AssignedTo'&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;displayName&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;WorkItemType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'System.WorkItemType'&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;StoryPoints&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'Microsoft.VSTS.Scheduling.StoryPoints'&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;AreaPath&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'System.AreaPath'&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;IterationPath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'System.IterationPath'&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;CreatedDate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'System.CreatedDate'&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;ChangedDate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'System.ChangedDate'&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;Tags&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'System.Tags'&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nv"&gt;$rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Export-Csv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$outputFile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-NoTypeInformation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Encoding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;UTF8&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Exported &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Count&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; work items to &lt;/span&gt;&lt;span class="nv"&gt;$outputFile&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Exporting pipeline runs with Python
&lt;/h3&gt;

&lt;p&gt;This Python script pulls pipeline run data - something the built-in export cannot do at all:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;

&lt;span class="c1"&gt;# Configuration
&lt;/span&gt;&lt;span class="n"&gt;ORG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-organization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;PROJECT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-project&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;PAT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-personal-access-token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;OUTPUT_FILE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pipeline-runs-export.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Auth setup
&lt;/span&gt;&lt;span class="n"&gt;credentials&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;b64encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PAT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Basic &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;credentials&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_pipeline_runs&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Fetch all pipeline runs with pagination.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;all_runs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://dev.azure.com/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ORG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PROJECT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/_apis/pipelines?api-version=7.1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pipelines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pipelines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]):&lt;/span&gt;
        &lt;span class="n"&gt;runs_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://dev.azure.com/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ORG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PROJECT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/_apis/pipelines/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/runs?api-version=7.1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;runs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;runs_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]):&lt;/span&gt;
            &lt;span class="n"&gt;all_runs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pipeline&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RunID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;State&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CreatedDate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;createdDate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FinishedDate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;finishedDate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SourceBranch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;resources&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
                &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;repositories&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
                &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;self&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
                &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;refName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;all_runs&lt;/span&gt;

&lt;span class="c1"&gt;# Export to CSV
&lt;/span&gt;&lt;span class="n"&gt;runs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_pipeline_runs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OUTPUT_FILE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DictWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fieldnames&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeheader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writerows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Exported &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; pipeline runs to &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;OUTPUT_FILE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Exporting pull request and code review data
&lt;/h3&gt;

&lt;p&gt;For teams that need code review audit trails, this Python snippet exports pull request data including reviewer votes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_pull_requests&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;completed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Export pull requests with reviewer details.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://dev.azure.com/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ORG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PROJECT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/_apis/git/repositories/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;repo_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/pullrequests?searchCriteria.status=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;amp;$top=1000&amp;amp;api-version=7.1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;pr&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]):&lt;/span&gt;
        &lt;span class="n"&gt;reviewers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;displayName&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;vote&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reviewers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PR_ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pullRequestId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CreatedBy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;createdBy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;displayName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CreatedDate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;creationDate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ClosedDate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;closedDate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SourceBranch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sourceRefName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TargetBranch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;targetRefName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MergeStatus&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mergeStatus&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Reviewers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reviewers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The vote values in Azure DevOps reviewer data map to: &lt;code&gt;10&lt;/code&gt; = Approved, &lt;code&gt;5&lt;/code&gt; = Approved with suggestions, &lt;code&gt;0&lt;/code&gt; = No vote, &lt;code&gt;-5&lt;/code&gt; = Wait for author, &lt;code&gt;-10&lt;/code&gt; = Rejected. Knowing this is essential when building compliance reports from exported data.&lt;/p&gt;

&lt;h3&gt;
  
  
  REST API tips
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Personal Access Tokens (PAT)&lt;/strong&gt; - generate one at &lt;code&gt;https://dev.azure.com/{org}/_usersSettings/tokens&lt;/code&gt; with the minimum required scopes (Work Items Read, Code Read, Build Read depending on what you are exporting)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pagination&lt;/strong&gt; - most API endpoints return a maximum of 200-1000 items per request. Use the &lt;code&gt;continuationToken&lt;/code&gt; or &lt;code&gt;$skip/$top&lt;/code&gt; parameters to page through large result sets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate limits&lt;/strong&gt; - Azure DevOps allows approximately 30 requests per second per user. Add a small delay between batch requests if you are exporting large datasets.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Method 4 - OData Analytics feeds in Excel
&lt;/h2&gt;

&lt;p&gt;Azure DevOps Analytics is an OData-based reporting service that provides optimized, queryable access to work tracking, pipeline, and test data. The major advantage over the REST API is that Analytics is designed for reporting - it supports aggregations, filtering, and projections at the server level, so you pull less data over the wire.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connecting Excel to Analytics OData
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Step 1 - Get your Analytics URL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The base URL format is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://analytics.dev.azure.com/{organization}/{project}/_odata/v4.0-preview/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Common entity sets you can query:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Entity&lt;/th&gt;
&lt;th&gt;URL Suffix&lt;/th&gt;
&lt;th&gt;Data Type&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Work items&lt;/td&gt;
&lt;td&gt;&lt;code&gt;WorkItems&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Current state of all work items&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Work item snapshots&lt;/td&gt;
&lt;td&gt;&lt;code&gt;WorkItemSnapshot&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Historical daily snapshots&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Work item revisions&lt;/td&gt;
&lt;td&gt;&lt;code&gt;WorkItemRevisions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Every change to every work item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pipeline runs&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PipelineRuns&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Build and release pipeline execution data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test results&lt;/td&gt;
&lt;td&gt;&lt;code&gt;TestResultsDaily&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Aggregated daily test pass/fail data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test runs&lt;/td&gt;
&lt;td&gt;&lt;code&gt;TestRuns&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Individual test run metadata&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Step 2 - Open Excel and connect to OData&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Excel and go to &lt;strong&gt;Data &amp;gt; Get Data &amp;gt; From Other Sources &amp;gt; From OData Feed&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Paste the Analytics URL, for example: &lt;code&gt;https://analytics.dev.azure.com/myorg/myproject/_odata/v4.0-preview/WorkItems?$select=WorkItemId,Title,State,WorkItemType,StoryPoints,AssignedTo&amp;amp;$filter=WorkItemType eq 'User Story'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;When prompted for authentication, select &lt;strong&gt;Basic&lt;/strong&gt; and enter an empty username with your PAT as the password. Alternatively, select &lt;strong&gt;Organizational Account&lt;/strong&gt; if your Excel is signed into the same Azure AD tenant.&lt;/li&gt;
&lt;li&gt;Excel will load the data into the Power Query editor where you can apply additional transformations.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Close &amp;amp; Load&lt;/strong&gt; to bring the data into a worksheet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Step 3 - Build your report&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With the data in Excel, create pivot tables, charts, and dashboards. The connection is refreshable - right-click the data table and select &lt;strong&gt;Refresh&lt;/strong&gt; to pull the latest data from Azure DevOps at any time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Useful OData query examples
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;All active bugs with priority and severity:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;WorkItems&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;WorkItemId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;State&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;Priority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;Severity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;AssignedTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;CreatedDate&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;WorkItemType&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt; &lt;span class="s1"&gt;'Bug'&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="k"&gt;State&lt;/span&gt; &lt;span class="n"&gt;ne&lt;/span&gt; &lt;span class="s1"&gt;'Closed'&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="k"&gt;State&lt;/span&gt; &lt;span class="n"&gt;ne&lt;/span&gt; &lt;span class="s1"&gt;'Removed'&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;orderby&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Priority&lt;/span&gt; &lt;span class="k"&gt;asc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Work item history for sprint analysis:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;WorkItemSnapshot&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Iteration&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;IterationPath&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt; &lt;span class="s1"&gt;'MyProject&lt;/span&gt;&lt;span class="se"&gt;\S&lt;/span&gt;&lt;span class="s1"&gt;print 15'&lt;/span&gt;
&lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;WorkItemType&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt; &lt;span class="s1"&gt;'User Story'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;DateSK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;State&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="k"&gt;aggregate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="k"&gt;count&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="k"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;orderby&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DateSK&lt;/span&gt; &lt;span class="k"&gt;asc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pipeline success rate by definition:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;PipelineRuns&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;PipelineName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;RunOutcome&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="k"&gt;aggregate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="k"&gt;count&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;RunCount&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  OData Analytics advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server-side filtering&lt;/strong&gt; - only the data you need crosses the network, making it much faster than pulling everything via REST API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aggregation support&lt;/strong&gt; - you can get counts, sums, and averages without downloading raw rows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Historical data&lt;/strong&gt; - snapshot entities provide daily point-in-time data that the REST API does not offer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refreshable in Excel&lt;/strong&gt; - set up the query once and refresh it whenever you need updated numbers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Method 5 - Power BI as an intermediate step
&lt;/h2&gt;

&lt;p&gt;While this guide focuses on Excel, Power BI deserves mention because it has the most polished integration with Azure DevOps Analytics, and you can easily export from Power BI to Excel.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to use the Power BI route
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You need complex data transformations before the data lands in Excel&lt;/li&gt;
&lt;li&gt;You want to combine data from multiple Azure DevOps projects into a single report&lt;/li&gt;
&lt;li&gt;Your organization already has Power BI licenses&lt;/li&gt;
&lt;li&gt;You need scheduled automatic refreshes (Power BI Service can refresh on a schedule and email Excel exports)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step-by-step Power BI to Excel workflow
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Step 1 - Install the Azure DevOps Power BI connector&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open Power BI Desktop. Click &lt;strong&gt;Get Data &amp;gt; Online Services &amp;gt; Azure DevOps&lt;/strong&gt;. If you do not see it, update Power BI Desktop to the latest version.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2 - Connect and build your report&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Enter your organization URL and authenticate. Select the data tables you need. Use Power Query to filter, join, and transform the data. Build visualizations if desired - or skip straight to the data model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 - Export to Excel&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Power BI Desktop, go to the data view. Select the table you want to export. Click &lt;strong&gt;Export Data&lt;/strong&gt; and choose CSV or Excel format. Alternatively, publish the report to Power BI Service and use the &lt;strong&gt;Analyze in Excel&lt;/strong&gt; feature to create a live-connected Excel workbook.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4 - Schedule automatic exports (Power BI Service)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you need recurring Excel exports, publish your report to Power BI Service, set up scheduled refresh, and use Power Automate to email the refreshed data as an Excel attachment on a schedule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 6 - Third-party tools and extensions
&lt;/h2&gt;

&lt;p&gt;The Visual Studio Marketplace and third-party ecosystem offer several tools that simplify Azure DevOps data export.&lt;/p&gt;

&lt;h3&gt;
  
  
  Azure DevOps Marketplace extensions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Enhanced Export (by Artiso)&lt;/strong&gt; - adds a one-click export button to query results with more formatting options than the built-in CSV export. Supports exporting to &lt;code&gt;.xlsx&lt;/code&gt; format directly with preserved column widths and header formatting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WIQL to OData (by Microsoft)&lt;/strong&gt; - converts work item queries to OData URLs that you can paste directly into Excel's OData connector. Useful if you are comfortable writing WIQL but not OData syntax.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Excel Export PRO&lt;/strong&gt; - a marketplace extension that supports exporting work items with parent-child hierarchies preserved in the Excel output, which the built-in CSV export flattens.&lt;/p&gt;

&lt;h3&gt;
  
  
  Power Automate (formerly Microsoft Flow)
&lt;/h3&gt;

&lt;p&gt;Power Automate can create automated workflows that export Azure DevOps data to Excel on a schedule:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use the &lt;strong&gt;Azure DevOps connector&lt;/strong&gt; trigger (e.g., "When a work item is updated")&lt;/li&gt;
&lt;li&gt;Add an &lt;strong&gt;Excel Online (Business)&lt;/strong&gt; action to write data to an Excel file in OneDrive or SharePoint&lt;/li&gt;
&lt;li&gt;Set up a recurrence trigger for daily or weekly full exports&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach is particularly useful for teams that want a continuously updated Excel dashboard without manual exports.&lt;/p&gt;

&lt;h3&gt;
  
  
  Azure CLI
&lt;/h3&gt;

&lt;p&gt;The Azure DevOps CLI extension (&lt;code&gt;az devops&lt;/code&gt;) provides command-line access to most Azure DevOps data. Combined with tools like &lt;code&gt;jq&lt;/code&gt; for JSON processing, you can script exports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install the Azure DevOps extension&lt;/span&gt;
az extension add &lt;span class="nt"&gt;--name&lt;/span&gt; azure-devops

&lt;span class="c"&gt;# Login and set defaults&lt;/span&gt;
az devops configure &lt;span class="nt"&gt;--defaults&lt;/span&gt; &lt;span class="nv"&gt;organization&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://dev.azure.com/myorg &lt;span class="nv"&gt;project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;myproject

&lt;span class="c"&gt;# Export work items from a query to JSON, then convert to CSV&lt;/span&gt;
az boards query &lt;span class="nt"&gt;--wiql&lt;/span&gt; &lt;span class="s2"&gt;"SELECT [System.Id], [System.Title], [System.State] FROM WorkItems WHERE [System.WorkItemType] = 'Bug'"&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; json | &lt;span class="se"&gt;\&lt;/span&gt;
  python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"

data = json.load(sys.stdin)
writer = csv.writer(sys.stdout)
writer.writerow(['ID', 'Title', 'State'])
for item in data:
    fields = item.get('fields', {})
    writer.writerow([
        item['id'],
        fields.get('System.Title', ''),
        fields.get('System.State', '')
    ])
"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; bugs-export.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exporting test results to Excel
&lt;/h2&gt;

&lt;p&gt;Test result data requires special handling because Azure DevOps stores it differently from work items.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using the REST API
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;export_test_results&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Export test results for a specific test plan.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Get test suites in the plan
&lt;/span&gt;    &lt;span class="n"&gt;suites_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://dev.azure.com/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ORG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PROJECT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/_apis/testplan/Plans/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;plan_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/suites?api-version=7.1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;suites&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;suites_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;all_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;suite&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;suites&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]):&lt;/span&gt;
        &lt;span class="c1"&gt;# Get test points (test case + configuration pairs)
&lt;/span&gt;        &lt;span class="n"&gt;points_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://dev.azure.com/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ORG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PROJECT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/_apis/testplan/Plans/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;plan_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/suites/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;suite&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/TestPoint?api-version=7.1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;points_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]):&lt;/span&gt;
            &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
            &lt;span class="n"&gt;all_results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SuiteName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;suite&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TestCaseId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;testCaseReference&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TestCaseName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;testCaseReference&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Configuration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;configuration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Outcome&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lastResultState&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Not Run&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tester&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tester&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;displayName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LastRunDate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lastResultDetails&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dateCompleted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;all_results&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using the OData Analytics feed
&lt;/h3&gt;

&lt;p&gt;For aggregated test data - especially trend analysis - the OData feed is more efficient:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;analytics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;azure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;_odata&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v4&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;preview&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;TestResultsDaily&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DateSK&lt;/span&gt; &lt;span class="n"&gt;ge&lt;/span&gt; &lt;span class="mi"&gt;20260101&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;DateSK&lt;/span&gt; &lt;span class="n"&gt;le&lt;/span&gt; &lt;span class="mi"&gt;20260320&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;DateSK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;TestOutcome&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="k"&gt;aggregate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ResultCount&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="k"&gt;sum&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;TotalCount&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;orderby&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DateSK&lt;/span&gt; &lt;span class="k"&gt;asc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste this URL into Excel's OData connector to get a daily breakdown of test pass/fail counts that you can chart over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best practices for Azure DevOps data exports
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Security considerations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Never hard-code PATs in scripts&lt;/strong&gt; - use environment variables, Azure Key Vault, or credential managers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use minimum-scope PATs&lt;/strong&gt; - if you only need to export work items, do not create a full-access token&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rotate PATs regularly&lt;/strong&gt; - set expiration dates of 90 days or less&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit exports for sensitive data&lt;/strong&gt; - work item descriptions and comments may contain customer information, credentials, or internal URLs that should not be shared in Excel files sent via email&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Performance optimization
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use OData &lt;code&gt;$select&lt;/code&gt;&lt;/strong&gt; - only request the fields you need instead of pulling entire entities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apply &lt;code&gt;$filter&lt;/code&gt; server-side&lt;/strong&gt; - filtering in Excel after downloading all data wastes bandwidth and time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch REST API requests&lt;/strong&gt; - use the batch endpoint (&lt;code&gt;_apis/wit/workitemsbatch&lt;/code&gt;) instead of individual GET requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache results locally&lt;/strong&gt; - if you run the same export daily, compare timestamps and only pull changed items using the &lt;code&gt;ChangedDate&lt;/code&gt; field&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Data freshness
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;REST API&lt;/strong&gt; - real-time data, reflects the current state immediately&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics OData&lt;/strong&gt; - data is typically 2-5 minutes behind, with some entities refreshing every 24 hours (snapshots)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in Excel export&lt;/strong&gt; - real-time data at the moment of export, but static until you refresh&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Power BI&lt;/strong&gt; - depends on your configured refresh schedule (minimum 30 minutes on Power BI Service)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Handling large datasets
&lt;/h3&gt;

&lt;p&gt;If your Azure DevOps project has tens of thousands of work items or months of pipeline history:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Partition your queries&lt;/strong&gt; - split by area path, iteration, date range, or work item type instead of exporting everything at once&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use continuation tokens&lt;/strong&gt; - the REST API returns a &lt;code&gt;x-ms-continuationtoken&lt;/code&gt; header when more results are available. Always check for it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consider Azure Data Factory&lt;/strong&gt; - for truly large-scale exports (millions of rows), Azure Data Factory has native Azure DevOps connectors and can write directly to Azure SQL or Data Lake, which Excel can then query&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Comparison of all six methods
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Data Types&lt;/th&gt;
&lt;th&gt;Automation&lt;/th&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Difficulty&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Open in Excel&lt;/td&gt;
&lt;td&gt;Work items only&lt;/td&gt;
&lt;td&gt;Manual with refresh&lt;/td&gt;
&lt;td&gt;Windows only&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSV export&lt;/td&gt;
&lt;td&gt;Work items only&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;td&gt;Any browser&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;REST API&lt;/td&gt;
&lt;td&gt;Everything&lt;/td&gt;
&lt;td&gt;Fully scriptable&lt;/td&gt;
&lt;td&gt;Any platform&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OData Analytics&lt;/td&gt;
&lt;td&gt;Work items, pipelines, tests&lt;/td&gt;
&lt;td&gt;Refreshable in Excel&lt;/td&gt;
&lt;td&gt;Any platform&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power BI&lt;/td&gt;
&lt;td&gt;Everything via Analytics&lt;/td&gt;
&lt;td&gt;Scheduled refresh&lt;/td&gt;
&lt;td&gt;Windows (Desktop)&lt;/td&gt;
&lt;td&gt;Medium-Hard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Third-party tools&lt;/td&gt;
&lt;td&gt;Varies by tool&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;td&gt;Easy-Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;For most teams, the recommended approach is:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the &lt;strong&gt;built-in CSV export&lt;/strong&gt; for quick one-time exports of work item queries&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;OData Analytics in Excel&lt;/strong&gt; for recurring reports that need refreshable data&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;REST API scripts&lt;/strong&gt; when you need pipeline, PR, or code review data that the built-in tools do not cover&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Power BI&lt;/strong&gt; when you need to combine data from multiple projects or create organization-wide dashboards that ultimately get shared as Excel files&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Troubleshooting common issues
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"Open in Excel" button is missing&lt;/strong&gt; - install the Azure DevOps Office Integration 2019 plugin from the Visual Studio Marketplace. If already installed, check that your Excel version is 2016 or later and that the Team add-in is enabled in Excel's Add-ins manager (File &amp;gt; Options &amp;gt; Add-ins).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSV export has garbled characters&lt;/strong&gt; - the file is UTF-8 encoded but Excel may default to a different encoding. Use Data &amp;gt; From Text/CSV and explicitly select UTF-8 encoding during import.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OData feed returns 401 Unauthorized&lt;/strong&gt; - verify your PAT has the Analytics read scope enabled. Go to your PAT settings and ensure the "Analytics (read)" permission is checked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;REST API returns 203 Non-Authoritative&lt;/strong&gt; - this usually means your PAT has expired or the Authorization header is malformed. Regenerate the PAT and double-check the Base64 encoding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Excel Power Query times out&lt;/strong&gt; - the OData query is returning too much data. Add &lt;code&gt;$filter&lt;/code&gt; and &lt;code&gt;$select&lt;/code&gt; parameters to reduce the result set. Also check your network connection and proxy settings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data does not match Azure DevOps UI&lt;/strong&gt; - Analytics data can lag 2-5 minutes behind the live system. For real-time accuracy, use the REST API instead of Analytics OData feeds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Exporting Azure DevOps data to Excel does not have to be painful. For work items, the built-in tools handle most use cases with a few clicks. For pipeline data, test results, and code review audit trails, the REST API and OData Analytics feeds give you access to everything Azure DevOps stores - you just need a script and a PAT.&lt;/p&gt;

&lt;p&gt;The key is choosing the right method for your specific use case. One-time exports are best served by CSV. Recurring reports belong in OData-connected Excel workbooks. Automated compliance workflows should use Power Automate or scheduled scripts. And large-scale analytics across multiple projects should flow through Power BI before landing in Excel.&lt;/p&gt;

&lt;p&gt;Start with the simplest method that meets your requirements, and only move to more complex approaches when you hit limitations with the simpler ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Can I export Azure DevOps work items directly to Excel?
&lt;/h3&gt;

&lt;p&gt;Yes. Azure DevOps has a built-in Open in Excel button on the Queries page that launches a connected Excel session via the Azure DevOps Office Integration plugin. You can also export query results as a CSV file and open that in Excel manually. Both methods work with any work item query you have saved or created.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I install the Azure DevOps Excel plugin?
&lt;/h3&gt;

&lt;p&gt;The Azure DevOps Office Integration plugin is included with Visual Studio 2019 and later. If you only have Excel, download the standalone Azure DevOps Office Integration installer from the Visual Studio Marketplace. After installation, you will see a Team ribbon tab in Excel with options to connect to Azure DevOps and pull work item data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I export Azure DevOps pipeline data to Excel?
&lt;/h3&gt;

&lt;p&gt;Azure DevOps does not have a built-in one-click export for pipeline data. You need to use the REST API to pull pipeline runs, stages, jobs, and task results as JSON, then convert that JSON to CSV or load it directly into Excel using Power Query. The Analytics service also exposes pipeline data through OData feeds that Excel can consume.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the row limit when exporting Azure DevOps data to Excel?
&lt;/h3&gt;

&lt;p&gt;The built-in Open in Excel feature supports up to 50,000 work items per query. CSV exports from the web UI are also capped at the query result limit. If you need more than 50,000 rows, use the REST API with pagination (continuation tokens) or connect through Power BI and OData, which can handle millions of records.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I export Azure DevOps test results to Excel?
&lt;/h3&gt;

&lt;p&gt;Use the Test Results REST API endpoint to pull test run data as JSON. You can also use the Analytics OData feed at &lt;a href="https://analytics.dev.azure.com/%7Borg%7D/%7Bproject%7D/_odata/v4.0-preview/TestResultsDaily" rel="noopener noreferrer"&gt;https://analytics.dev.azure.com/{org}/{project}/_odata/v4.0-preview/TestResultsDaily&lt;/a&gt;. Both methods let you load data into Excel via Power Query or convert JSON to CSV with a script.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is Power BI required to export Azure DevOps analytics data?
&lt;/h3&gt;

&lt;p&gt;No. Power BI is one option, but you can also connect Excel directly to Azure DevOps Analytics using OData feeds. In Excel, go to Data &amp;gt; Get Data &amp;gt; From OData Feed and paste your Analytics URL. Excel will load the data into a table that you can refresh, filter, and pivot without needing Power BI at all.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://aicodereview.cc/blog/export-azure-devops-data-excel/" rel="noopener noreferrer"&gt;aicodereview.cc&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>ai</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Claude Code vs Codex CLI vs Gemini CLI: Which AI Terminal Agent Wins in 2026?</title>
      <dc:creator>Rahul Singh</dc:creator>
      <pubDate>Sat, 11 Apr 2026 06:00:00 +0000</pubDate>
      <link>https://dev.to/rahulxsingh/claude-code-vs-codex-cli-vs-gemini-cli-which-ai-terminal-agent-wins-in-2026-55f5</link>
      <guid>https://dev.to/rahulxsingh/claude-code-vs-codex-cli-vs-gemini-cli-which-ai-terminal-agent-wins-in-2026-55f5</guid>
      <description>&lt;h2&gt;
  
  
  Quick verdict
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/tool/claude-code/"&gt;Claude Code&lt;/a&gt; is the most capable AI terminal coding agent in 2026, offering the deepest code reasoning, best multi-file editing, and a proven multi-agent Code Review system. &lt;a href="https://dev.to/tool/openai-codex/"&gt;Codex CLI&lt;/a&gt; is the best free, open-source option with strong autonomous task execution in sandboxed environments. &lt;a href="https://dev.to/tool/gemini-code-assist/"&gt;Gemini CLI&lt;/a&gt; wins on context window size and free-tier generosity, making it ideal for large codebases and budget-conscious developers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose Claude Code if:&lt;/strong&gt; You want the best code reasoning, multi-file editing, and code review capabilities and are willing to pay for a premium experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose Codex CLI if:&lt;/strong&gt; You want an open-source CLI with autonomous cloud execution, parallel task support, and you already use ChatGPT or OpenAI's API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose Gemini CLI if:&lt;/strong&gt; You need the largest context window (1M tokens), want the most generous free tier, or your team is invested in the Google Cloud ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why AI terminal agents matter
&lt;/h2&gt;

&lt;p&gt;AI coding has moved beyond autocomplete. The latest generation of AI tools runs directly in your terminal, reads your entire codebase, edits multiple files, runs tests, commits changes, and even reviews pull requests - all from the command line.&lt;/p&gt;

&lt;p&gt;Three tools dominate this space in 2026: Claude Code from Anthropic, Codex CLI from OpenAI, and Gemini CLI from Google. Each takes a different approach to terminal-based AI coding, and choosing the wrong one can cost your team hours of productivity every week.&lt;/p&gt;

&lt;p&gt;This comparison breaks down every meaningful difference so you can pick the right tool for your workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  At-a-glance comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Claude Code&lt;/th&gt;
&lt;th&gt;Codex CLI&lt;/th&gt;
&lt;th&gt;Gemini CLI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Developer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Anthropic&lt;/td&gt;
&lt;td&gt;OpenAI&lt;/td&gt;
&lt;td&gt;Google&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Underlying model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Claude Opus 4.6 / Sonnet 4.6&lt;/td&gt;
&lt;td&gt;GPT-5-Codex&lt;/td&gt;
&lt;td&gt;Gemini 2.5 Pro / Flash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Context window&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;200K tokens&lt;/td&gt;
&lt;td&gt;128K-200K tokens&lt;/td&gt;
&lt;td&gt;1M tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Free tier&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No (Pro from $20/mo)&lt;/td&gt;
&lt;td&gt;Open-source CLI (API costs apply)&lt;/td&gt;
&lt;td&gt;180K completions/month + 240 chats/day&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Starting price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$20/month (Pro)&lt;/td&gt;
&lt;td&gt;$20/month (ChatGPT Plus)&lt;/td&gt;
&lt;td&gt;Free / $19/user/month (Standard)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Open source&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (Apache 2.0)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-file editing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes - best in class&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Code review&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Multi-agent PR review&lt;/td&gt;
&lt;td&gt;PR review via GitHub&lt;/td&gt;
&lt;td&gt;Automated PR summaries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sandboxing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Local with permission system&lt;/td&gt;
&lt;td&gt;Cloud sandboxes + local&lt;/td&gt;
&lt;td&gt;Local execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MCP support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native (protocol creator)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Git integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Deep GitHub + local git&lt;/td&gt;
&lt;td&gt;GitHub-focused&lt;/td&gt;
&lt;td&gt;GitHub integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IDE extensions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;VS Code + JetBrains&lt;/td&gt;
&lt;td&gt;VS Code, Cursor, Windsurf&lt;/td&gt;
&lt;td&gt;VS Code, JetBrains, Android Studio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Extended thinking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agent orchestration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Agent Teams (sub-agents)&lt;/td&gt;
&lt;td&gt;Parallel cloud sandboxes&lt;/td&gt;
&lt;td&gt;Agent mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Headless / CI mode&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes (GitHub Action)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SWE-bench score&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Top tier&lt;/td&gt;
&lt;td&gt;State-of-the-art&lt;/td&gt;
&lt;td&gt;63.8%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Installation and setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Claude Code
&lt;/h3&gt;

&lt;p&gt;Claude Code installs via npm and runs as a standalone CLI. Setup takes under two minutes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @anthropic-ai/claude-code
claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On first run, it authenticates through your Anthropic account or API key. You can use it with a Pro subscription ($20/month), a Max plan ($100-$200/month), or pay-per-token via the API. The CLI works on macOS and Linux natively, with Windows support through WSL2.&lt;/p&gt;

&lt;h3&gt;
  
  
  Codex CLI
&lt;/h3&gt;

&lt;p&gt;Codex CLI is open source and built in Rust for speed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @openai/codex
codex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It requires an OpenAI API key, which you set as the &lt;code&gt;OPENAI_API_KEY&lt;/code&gt; environment variable. Alternatively, you can access Codex through a ChatGPT Plus subscription for cloud-based task execution. The CLI runs on macOS, Linux, and Windows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gemini CLI
&lt;/h3&gt;

&lt;p&gt;Gemini CLI installs via npm and authenticates through a Google account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @google/gemini-cli
gemini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The free tier requires no credit card or Google Cloud project - just a Google account. For team features and higher limits, you need a Standard ($19/user/month) or Enterprise ($45/user/month) plan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Gemini CLI&lt;/strong&gt; for the frictionless free setup. Codex CLI earns points for being open source. Claude Code's install is simple but requires a paid plan to start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context window and codebase understanding
&lt;/h2&gt;

&lt;p&gt;The context window determines how much of your codebase the AI can "see" at once. This matters enormously for large projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemini CLI&lt;/strong&gt; leads with a 1M token context window - roughly 3 to 4 million characters of code. This is enough to hold an entire mid-sized codebase in context without any chunking or summarization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Code&lt;/strong&gt; offers 200K tokens, which covers most individual features or modules comfortably. It compensates for the smaller window with intelligent codebase indexing and the ability to spawn sub-agents that explore different parts of your project in parallel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Codex CLI&lt;/strong&gt; supports 128K to 200K tokens depending on the model. It uses repository mapping and retrieval-augmented generation to find relevant code beyond the immediate context window.&lt;/p&gt;

&lt;p&gt;In practice, the raw context window size matters less than how intelligently each tool uses it. Claude Code's 200K window with strong reasoning often produces better results than Gemini CLI's 1M window on tasks where deep understanding trumps breadth. But for tasks like "refactor all API endpoints across 50 files," Gemini CLI's larger window gives it a genuine edge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Gemini CLI&lt;/strong&gt; on raw capacity. Claude Code on effective use of context for complex reasoning tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code generation quality
&lt;/h2&gt;

&lt;p&gt;This is where the underlying models make the biggest difference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Code&lt;/strong&gt; produces the most consistently correct and well-structured code. Claude Opus 4.6 excels at understanding complex requirements, generating idiomatic code, handling edge cases, and writing code that follows existing project conventions. The extended thinking feature lets it reason through multi-step problems before writing a single line, which dramatically reduces bugs in complex implementations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Codex CLI&lt;/strong&gt; generates strong code through GPT-5-Codex, which achieves state-of-the-art scores on SWE-bench. It is particularly good at autonomous task execution - you can describe a feature and it will write the code, create tests, and verify everything passes. The quality is high for straightforward tasks but can struggle with highly nuanced architectural decisions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemini CLI&lt;/strong&gt; produces good code with Gemini 2.5 Pro, especially for Google Cloud services, Android development, and Python. The large context window helps it maintain consistency across large changes. However, users report occasional hallucinations in generated code, particularly for less common libraries or frameworks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Claude Code&lt;/strong&gt; for overall code quality and reasoning depth. Codex CLI for autonomous task completion. Gemini CLI for Google ecosystem work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-file editing and refactoring
&lt;/h2&gt;

&lt;p&gt;Real-world coding involves changing multiple files simultaneously. All three tools handle this, but the experience differs significantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Code&lt;/strong&gt; is the clear leader here. It can read your entire project structure, understand the relationships between files, and make coordinated changes across dozens of files while maintaining consistency. Renaming a function, updating all call sites, adjusting tests, and modifying documentation happens in a single interaction. The sub-agent system lets it delegate different parts of a large refactoring to parallel workers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Codex CLI&lt;/strong&gt; handles multi-file editing through its autonomous task execution. You describe the change, and it works through the files systematically in a sandboxed environment. The isolated Git worktree approach means your working directory stays clean while Codex makes changes in the background. The trade-off is less interactive control during the process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemini CLI&lt;/strong&gt; supports multi-file editing through its agent mode, and the 1M token context window means it can hold more files in memory simultaneously. However, the actual edit coordination is less refined than Claude Code's, and complex cross-file refactoring sometimes requires multiple prompts to get right.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Claude Code&lt;/strong&gt; by a significant margin. Its multi-file editing and refactoring capabilities are the most reliable and comprehensive of the three.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git integration and workflow
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Claude Code
&lt;/h3&gt;

&lt;p&gt;Claude Code has the deepest Git integration of the three. It understands your Git history, can create branches, stage changes, write commit messages, create pull requests, and even resolve merge conflicts. The multi-agent Code Review feature runs parallel AI agents to review PRs, with Anthropic reporting that it raised substantial review comment rates from 16% to 54% of PRs internally, with less than 1% of findings being incorrect.&lt;/p&gt;

&lt;p&gt;You can run Claude Code in headless mode in CI/CD pipelines, making it useful for automated code review on every PR.&lt;/p&gt;

&lt;h3&gt;
  
  
  Codex CLI
&lt;/h3&gt;

&lt;p&gt;Codex CLI integrates tightly with GitHub. You can trigger tasks from PR comments using &lt;a class="mentioned-user" href="https://dev.to/codex"&gt;@codex&lt;/a&gt;, and it has a GitHub Action for CI/CD integration. Cloud-based tasks run in isolated sandboxes with their own Git worktrees, so multiple tasks can work on different branches simultaneously. The PR review capability is functional but oriented more toward autonomous fixes than detailed review commentary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gemini CLI
&lt;/h3&gt;

&lt;p&gt;Gemini CLI provides GitHub integration with automated PR summaries and review comments. The integration is straightforward but not as deep as Claude Code's multi-agent review system. There is no headless or CI/CD mode, which limits automation possibilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Claude Code&lt;/strong&gt; for the deepest Git workflow integration and most capable code review. Codex CLI for autonomous GitHub-based task execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sandboxing and safety
&lt;/h2&gt;

&lt;p&gt;Running AI-generated code carries risk. Each tool handles safety differently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Codex CLI&lt;/strong&gt; has the strongest sandboxing. Cloud tasks run in fully isolated sandbox environments with their own file systems and network access. Locally, you can configure different permission levels - from read-only to full autonomy. The sandbox approach means a misbehaving AI cannot corrupt your working directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Code&lt;/strong&gt; uses a permission-based system. It asks before reading sensitive files, running commands, or making changes. You can configure permission levels to auto-approve safe operations while requiring confirmation for destructive ones. Hooks let you add pre/post action automation for additional guardrails. However, it runs locally by default, not in an isolated sandbox.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemini CLI&lt;/strong&gt; runs locally with standard permission prompts. There is no sandboxed execution environment - it operates directly on your file system with whatever permissions your terminal session has.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Codex CLI&lt;/strong&gt; for its cloud sandbox isolation. Claude Code for its configurable permission system. Gemini CLI trails here with minimal safety features.&lt;/p&gt;

&lt;h2&gt;
  
  
  MCP (Model Context Protocol) support
&lt;/h2&gt;

&lt;p&gt;MCP lets AI tools connect to external data sources, APIs, and services. This is increasingly important as developers want their AI coding agents to access databases, documentation, monitoring systems, and other tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Code&lt;/strong&gt; has the most mature MCP support, which makes sense since Anthropic created the Model Context Protocol. It can connect to any MCP server natively, with a large and growing ecosystem of available servers for databases, APIs, documentation, and more. The integration is seamless - you configure MCP servers in your project settings and Claude Code can pull data from them during coding sessions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Codex CLI&lt;/strong&gt; added MCP server support for extensibility. The implementation is functional and growing, though the ecosystem of available Codex-compatible MCP servers is smaller than Claude Code's.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemini CLI&lt;/strong&gt; supports MCP for connecting to external tools and data sources. Google has been expanding its MCP support, but the ecosystem is still catching up to Anthropic's.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Claude Code&lt;/strong&gt; as the creator and most mature implementer of MCP. All three support it, but Claude Code's ecosystem is the most developed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan tier&lt;/th&gt;
&lt;th&gt;Claude Code&lt;/th&gt;
&lt;th&gt;Codex CLI&lt;/th&gt;
&lt;th&gt;Gemini CLI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No free tier&lt;/td&gt;
&lt;td&gt;CLI is free (API costs apply)&lt;/td&gt;
&lt;td&gt;180K completions/month + 240 chats/day&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Individual&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$20/month (Pro)&lt;/td&gt;
&lt;td&gt;$20/month (ChatGPT Plus)&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Power user&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$100-$200/month (Max)&lt;/td&gt;
&lt;td&gt;$200/month (ChatGPT Pro)&lt;/td&gt;
&lt;td&gt;$19/user/month (Standard)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Team&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$25-$150/user/month&lt;/td&gt;
&lt;td&gt;$25/user/month&lt;/td&gt;
&lt;td&gt;$19/user/month (Standard)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Enterprise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Custom&lt;/td&gt;
&lt;td&gt;Custom&lt;/td&gt;
&lt;td&gt;$45/user/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API usage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$3-$25/M tokens&lt;/td&gt;
&lt;td&gt;Usage-based&lt;/td&gt;
&lt;td&gt;Usage-based&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Gemini CLI&lt;/strong&gt; is the clear pricing winner with its generous free tier. For a 10-person team, Gemini CLI at $19/user/month ($190/month) is significantly cheaper than Claude Code at $25-$150/user/month ($250-$1,500/month) or Codex CLI at $25/user/month ($250/month).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Codex CLI&lt;/strong&gt; offers a unique value proposition as an open-source tool. If you only need occasional terminal AI assistance and already have OpenAI API credits, the per-token cost can be very low.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Code&lt;/strong&gt; is the most expensive option, but the API usage-based pricing gives flexibility. Light users can spend $5-$10/month on API calls, while heavy users might spend $50+ per day on complex tasks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Gemini CLI&lt;/strong&gt; on value. Codex CLI for open-source flexibility. Claude Code demands a premium but delivers premium results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extended thinking and reasoning
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Claude Code&lt;/strong&gt; is the only tool with a dedicated extended thinking mode. When you give it a complex task - debugging a race condition, designing a system architecture, or refactoring a tightly coupled module - it can activate extended thinking to reason through the problem step by step before acting. This produces noticeably better results on hard problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Codex CLI&lt;/strong&gt; and &lt;strong&gt;Gemini CLI&lt;/strong&gt; do not have equivalent features. They process prompts through their respective models' standard inference pipelines, which are capable but lack the explicit chain-of-thought reasoning that extended thinking provides.&lt;/p&gt;

&lt;p&gt;For simple tasks like "add a loading spinner to this component," the difference is negligible. For complex tasks like "refactor this authentication system to support SAML SSO," extended thinking gives Claude Code a meaningful advantage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Claude Code&lt;/strong&gt; - no contest on this dimension.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-world performance
&lt;/h2&gt;

&lt;p&gt;Beyond benchmarks, here is how each tool performs in daily development work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Claude Code in practice
&lt;/h3&gt;

&lt;p&gt;Claude Code feels like a senior developer who lives in your terminal. It understands project structure intuitively, asks clarifying questions when requirements are ambiguous, and makes changes that respect existing code conventions. The Agent Teams feature lets you spin up multiple agents for parallel work on a large task. The main friction points are rate limits on the Pro plan during heavy sessions and the learning curve for developers not comfortable with CLIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Codex CLI in practice
&lt;/h3&gt;

&lt;p&gt;Codex CLI excels at "fire and forget" tasks. You describe what you want, and it works autonomously in a cloud sandbox while you continue other work. The parallel task execution is genuinely useful - you can queue up five bug fixes and review the results as each one completes. The main downsides are GitHub-only integration (no GitLab or Bitbucket), occasional latency with cloud tasks, and usage limits on the Plus plan.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gemini CLI in practice
&lt;/h3&gt;

&lt;p&gt;Gemini CLI impresses with its free tier and large context window. For developers working on large codebases, the ability to load nearly everything into context reduces the "lost context" problems that plague smaller-window tools. The Google Cloud integration is excellent if you are building on GCP. The main weaknesses are occasional hallucinations, slower response times compared to Claude Code, and the lack of a headless CI/CD mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should use what
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Choose Claude Code if you:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Want the best code reasoning and generation quality available&lt;/li&gt;
&lt;li&gt;Need reliable multi-file editing and complex refactoring&lt;/li&gt;
&lt;li&gt;Value multi-agent Code Review for your PR workflow&lt;/li&gt;
&lt;li&gt;Need CI/CD integration via headless mode&lt;/li&gt;
&lt;li&gt;Are willing to pay a premium for premium results&lt;/li&gt;
&lt;li&gt;Want the most mature MCP ecosystem&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Choose Codex CLI if you:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Prefer open-source tools you can inspect and modify&lt;/li&gt;
&lt;li&gt;Want autonomous cloud-based task execution&lt;/li&gt;
&lt;li&gt;Need to run multiple coding tasks in parallel&lt;/li&gt;
&lt;li&gt;Are already in the OpenAI/ChatGPT ecosystem&lt;/li&gt;
&lt;li&gt;Want fire-and-forget task queuing&lt;/li&gt;
&lt;li&gt;Need Windows support without WSL&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Choose Gemini CLI if you:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Need the largest context window for massive codebases&lt;/li&gt;
&lt;li&gt;Want the best free tier for individual use&lt;/li&gt;
&lt;li&gt;Build on Google Cloud Platform&lt;/li&gt;
&lt;li&gt;Are budget-conscious with a team needing AI coding tools&lt;/li&gt;
&lt;li&gt;Work primarily with Python, Java, or Go&lt;/li&gt;
&lt;li&gt;Want a low-friction entry point to AI terminal coding&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;All three AI terminal agents are capable tools that can meaningfully accelerate your development workflow. The right choice depends on your priorities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For code quality and reasoning:&lt;/strong&gt; &lt;a href="https://dev.to/tool/claude-code/"&gt;Claude Code&lt;/a&gt; wins. Its extended thinking, multi-agent architecture, and superior code comprehension make it the best tool for complex, real-world development tasks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For autonomous execution and open-source values:&lt;/strong&gt; &lt;a href="https://dev.to/tool/openai-codex/"&gt;Codex CLI&lt;/a&gt; wins. Its sandboxed cloud execution, parallel task support, and Apache 2.0 license make it uniquely flexible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For budget and context window:&lt;/strong&gt; &lt;a href="https://dev.to/tool/gemini-code-assist/"&gt;Gemini CLI&lt;/a&gt; wins. The 1M token context window and generous free tier make it the most accessible and cost-effective option.&lt;/p&gt;

&lt;p&gt;If budget is not a constraint and you want the single best AI coding experience in your terminal, Claude Code is the tool to pick. If you are evaluating for a team, consider starting with Gemini CLI's free tier to validate the workflow, then upgrading to Claude Code or Codex CLI once you understand your team's usage patterns.&lt;/p&gt;

&lt;p&gt;For teams that also need &lt;a href="https://dev.to/blog/how-to-automate-code-review/"&gt;automated code review&lt;/a&gt;, Claude Code's multi-agent review system or a dedicated tool like &lt;a href="https://dev.to/tool/coderabbit/"&gt;CodeRabbit&lt;/a&gt; will give you the deepest PR feedback. You can also explore our roundup of the &lt;a href="https://dev.to/blog/best-ai-code-review-tools/"&gt;best AI code review tools&lt;/a&gt; for more options.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Which AI terminal coding agent is best overall in 2026?
&lt;/h3&gt;

&lt;p&gt;Claude Code is the best overall AI terminal coding agent in 2026. It offers the deepest code reasoning, the most mature multi-file editing, built-in extended thinking for complex tasks, and a proven multi-agent Code Review feature. Codex CLI is better if you want a free open-source tool for quick edits, and Gemini CLI is the best option if you need a massive 1M token context window on a budget.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is Codex CLI free to use?
&lt;/h3&gt;

&lt;p&gt;Yes, Codex CLI is fully open source under the Apache 2.0 license. However, you still need an OpenAI API key with credits to run it since it calls OpenAI models. The CLI itself costs nothing, but API usage is billed per token. You can also use it through a ChatGPT Plus subscription at $20/month, which gives you 30 to 150 tasks per 5-hour window depending on the model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can Claude Code, Codex CLI, and Gemini CLI all do code review?
&lt;/h3&gt;

&lt;p&gt;All three can analyze code and suggest improvements, but their approaches differ. Claude Code has a dedicated multi-agent Code Review feature that runs multiple AI agents in parallel to review pull requests, catching subtle bugs with less than 1% incorrect findings. Codex CLI can review PRs through its GitHub integration and by mentioning &lt;a class="mentioned-user" href="https://dev.to/codex"&gt;@codex&lt;/a&gt; in PR comments. Gemini CLI integrates with GitHub for automated PR summaries and review comments. For dedicated code review, Claude Code is the most capable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which AI CLI tool has the largest context window?
&lt;/h3&gt;

&lt;p&gt;Gemini CLI has the largest context window at 1 million tokens, powered by Gemini 2.5 Pro. Claude Code supports up to 200K tokens with Claude Opus 4.6. Codex CLI varies by model but typically supports 128K to 200K tokens with GPT-5-Codex. For extremely large codebases where you need full-repository context, Gemini CLI has a significant advantage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do these AI CLI tools support MCP (Model Context Protocol)?
&lt;/h3&gt;

&lt;p&gt;Yes, all three support MCP to varying degrees. Claude Code has the deepest MCP integration since Anthropic created the protocol - it can connect to databases, APIs, documentation servers, and custom tools natively. Codex CLI added MCP server support for extensibility. Gemini CLI also supports MCP for connecting to external tools and data sources. Claude Code's MCP ecosystem is the most mature with the largest number of available servers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which AI terminal agent is best for large monorepos?
&lt;/h3&gt;

&lt;p&gt;Gemini CLI is the strongest choice for very large monorepos thanks to its 1M token context window, which lets it hold significantly more code in memory at once. Claude Code compensates with intelligent codebase indexing and sub-agent spawning that can explore different parts of a monorepo in parallel. Codex CLI handles monorepos through isolated Git worktrees but has a smaller context window. For monorepos under 200K tokens, Claude Code's superior reasoning gives better results despite the smaller window.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://aicodereview.cc/blog/claude-code-vs-codex-cli-vs-gemini-cli/" rel="noopener noreferrer"&gt;aicodereview.cc&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>ai</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>13 Best Duplicate Code Checker Tools in 2026</title>
      <dc:creator>Rahul Singh</dc:creator>
      <pubDate>Fri, 10 Apr 2026 23:00:00 +0000</pubDate>
      <link>https://dev.to/rahulxsingh/13-best-duplicate-code-checker-tools-in-2026-1cnk</link>
      <guid>https://dev.to/rahulxsingh/13-best-duplicate-code-checker-tools-in-2026-1cnk</guid>
      <description>&lt;h2&gt;
  
  
  Code duplication is the silent tax on every codebase
&lt;/h2&gt;

&lt;p&gt;I have worked on codebases where fixing a single bug required changing the same logic in seven different files. Not because the architecture demanded it - because someone copy-pasted a function years ago, and then someone else copy-pasted the copy, and then the copies diverged slightly, and nobody knew which version was canonical anymore.&lt;/p&gt;

&lt;p&gt;That is the real cost of code duplication. It is not just wasted disk space or inflated line counts. It is the compounding maintenance burden of keeping multiple copies of the same logic in sync - a task that humans are reliably terrible at.&lt;/p&gt;

&lt;p&gt;Studies from large-scale codebases confirm this. Research on the Linux kernel found that inconsistent changes to cloned code were responsible for a meaningful percentage of bugs. A study of open-source Java projects found that cloned code was changed more frequently and contained more defects than non-cloned code. The numbers vary by study, but the pattern is consistent: duplication breeds bugs.&lt;/p&gt;

&lt;p&gt;The good news is that detecting duplicate code is a well-understood problem with excellent tooling. This guide covers 13 tools that find duplicated code - from lightweight CLI utilities you can run in 30 seconds to full platforms that track duplication trends across your entire organization.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is code duplication (and why should you care)?
&lt;/h2&gt;

&lt;p&gt;Code duplication - also called code cloning - occurs when identical or nearly identical code fragments exist in multiple locations within a codebase. It typically happens through copy-paste programming, where a developer copies a working block of code and modifies it slightly for a new context instead of abstracting the shared logic into a reusable function.&lt;/p&gt;

&lt;h3&gt;
  
  
  The four types of code clones
&lt;/h3&gt;

&lt;p&gt;The research community classifies code clones into four types, and this taxonomy matters because different tools detect different types:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Type 1 - Exact clones.&lt;/strong&gt; Identical code fragments except for differences in whitespace, layout, and comments. This is the simplest form - someone copied a function and only changed the formatting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Clone A&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculateTax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.08&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Clone B (Type 1 - only whitespace differs)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculateTax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.08&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Type 2 - Renamed clones.&lt;/strong&gt; Syntactically identical fragments with differences in identifier names, literal values, or type declarations. The structure is the same, but names and values have changed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Clone A&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculateTax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.08&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Clone B (Type 2 - renamed variables and changed literal)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;computeLevy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;percentage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;percentage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Type 3 - Near-miss clones.&lt;/strong&gt; Fragments with further modifications - statements added, removed, or reordered. The code is recognizably similar but not structurally identical.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Clone A&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculateTax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.08&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Clone B (Type 3 - added validation logic)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;computeLevy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid price&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;percentage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;percentage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Levy: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Type 4 - Semantic clones.&lt;/strong&gt; Functionally equivalent code implemented with different syntax or algorithms. Two sorting functions that use different algorithms but produce identical output are Type 4 clones. These are the hardest to detect and most tools cannot reliably find them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why duplication matters
&lt;/h3&gt;

&lt;p&gt;The DRY (Don't Repeat Yourself) principle exists for practical reasons, not aesthetic ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bug propagation.&lt;/strong&gt; A bug fixed in one copy often remains unfixed in the others. The more copies, the more likely a fix will be incomplete.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintenance cost.&lt;/strong&gt; Every change to shared logic must be applied N times across N copies. This scales linearly with duplication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code review burden.&lt;/strong&gt; Reviewers waste time reading code they have already reviewed in another file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Binary size and build time.&lt;/strong&gt; Duplicated code inflates compilation and bundle sizes unnecessarily.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inconsistent behavior.&lt;/strong&gt; When copies diverge, users encounter different behavior depending on which code path they hit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not all duplication is harmful. Test files, generated code, and certain boilerplate patterns are often intentionally duplicated. The goal is not zero duplication - it is zero &lt;em&gt;accidental&lt;/em&gt; duplication of business logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tool comparison table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Clone Types&lt;/th&gt;
&lt;th&gt;Languages&lt;/th&gt;
&lt;th&gt;Pricing&lt;/th&gt;
&lt;th&gt;CI Integration&lt;/th&gt;
&lt;th&gt;Open Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SonarQube&lt;/td&gt;
&lt;td&gt;1, 2, 3&lt;/td&gt;
&lt;td&gt;35+&lt;/td&gt;
&lt;td&gt;Free (Community) to $65K+/yr&lt;/td&gt;
&lt;td&gt;GitHub, GitLab, Jenkins, Azure&lt;/td&gt;
&lt;td&gt;Community Build: Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PMD CPD&lt;/td&gt;
&lt;td&gt;1, 2&lt;/td&gt;
&lt;td&gt;20+&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Maven, Gradle, CLI&lt;/td&gt;
&lt;td&gt;Yes (BSD)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Simian&lt;/td&gt;
&lt;td&gt;1, 2&lt;/td&gt;
&lt;td&gt;15+&lt;/td&gt;
&lt;td&gt;$299-$499/license&lt;/td&gt;
&lt;td&gt;CLI, Ant, Maven&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;jscpd&lt;/td&gt;
&lt;td&gt;1, 2&lt;/td&gt;
&lt;td&gt;150+ (via tokenizers)&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;CLI, GitHub Actions&lt;/td&gt;
&lt;td&gt;Yes (MIT)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MOSS&lt;/td&gt;
&lt;td&gt;1, 2, 3&lt;/td&gt;
&lt;td&gt;25+&lt;/td&gt;
&lt;td&gt;Free (academic)&lt;/td&gt;
&lt;td&gt;Web upload only&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Duplo&lt;/td&gt;
&lt;td&gt;1, 2&lt;/td&gt;
&lt;td&gt;Language-agnostic&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;CLI&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CloneDR&lt;/td&gt;
&lt;td&gt;1, 2, 3, 4&lt;/td&gt;
&lt;td&gt;20+&lt;/td&gt;
&lt;td&gt;Enterprise pricing&lt;/td&gt;
&lt;td&gt;CLI&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CodeAnt AI&lt;/td&gt;
&lt;td&gt;1, 2, 3&lt;/td&gt;
&lt;td&gt;30+&lt;/td&gt;
&lt;td&gt;Free to $40/user/mo&lt;/td&gt;
&lt;td&gt;GitHub, GitLab, Bitbucket&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Codacy&lt;/td&gt;
&lt;td&gt;1, 2&lt;/td&gt;
&lt;td&gt;40+&lt;/td&gt;
&lt;td&gt;Free to $15/user/mo&lt;/td&gt;
&lt;td&gt;GitHub, GitLab, Bitbucket&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSource&lt;/td&gt;
&lt;td&gt;1, 2, 3&lt;/td&gt;
&lt;td&gt;15+&lt;/td&gt;
&lt;td&gt;Free to $12/user/mo&lt;/td&gt;
&lt;td&gt;GitHub, GitLab, Bitbucket&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IntelliJ IDEA&lt;/td&gt;
&lt;td&gt;1, 2, 3&lt;/td&gt;
&lt;td&gt;JVM, Python, JS, PHP&lt;/td&gt;
&lt;td&gt;$249-$779/yr (Ultimate)&lt;/td&gt;
&lt;td&gt;IDE only&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coverity&lt;/td&gt;
&lt;td&gt;1, 2, 3&lt;/td&gt;
&lt;td&gt;22+&lt;/td&gt;
&lt;td&gt;Enterprise pricing ($50K+)&lt;/td&gt;
&lt;td&gt;Jenkins, GitHub, GitLab&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Semgrep&lt;/td&gt;
&lt;td&gt;1, 2 (pattern-based)&lt;/td&gt;
&lt;td&gt;30+&lt;/td&gt;
&lt;td&gt;Free (OSS) to custom&lt;/td&gt;
&lt;td&gt;GitHub, GitLab, CLI&lt;/td&gt;
&lt;td&gt;OSS engine: Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  1. SonarQube - copy-paste detection built into the quality platform
&lt;/h2&gt;

&lt;p&gt;SonarQube's duplication detection is one of the most widely deployed in the industry, largely because it comes bundled with the broader quality platform that most enterprises already run. If you are using SonarQube for code quality and security, you are already getting duplication analysis for free.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works.&lt;/strong&gt; SonarQube uses a combination of token-based and AST-based analysis depending on the language. For most languages, it tokenizes code, normalizes identifiers and literals, and then finds matching token sequences above a configurable minimum length (default: 100 tokens for Java, 120 for JavaScript). It detects Type 1, Type 2, and some Type 3 clones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What sets it apart.&lt;/strong&gt; The duplication metrics feed directly into SonarQube's quality gate system. You can block merges when duplication on new code exceeds a threshold - 3% is the default. The duplication visualization shows exactly which blocks are duplicated and where, making it easy to plan refactoring.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 35+ including Java, Python, JavaScript, TypeScript, C#, C/C++, Go, PHP, Ruby, Swift, Kotlin.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Community Build is free and open source. Developer Edition starts around $150/year for 100K LOC. Enterprise runs $65,000+/year.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplication detection is part of a comprehensive quality platform&lt;/li&gt;
&lt;li&gt;Quality gates can enforce duplication thresholds on PRs&lt;/li&gt;
&lt;li&gt;Excellent visualization of duplicate blocks across the codebase&lt;/li&gt;
&lt;li&gt;Deep language support with language-specific tokenization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Community Build requires self-hosting a server&lt;/li&gt;
&lt;li&gt;Configuration is heavier than standalone CLI tools&lt;/li&gt;
&lt;li&gt;Enterprise pricing is steep for teams that only need duplication detection&lt;/li&gt;
&lt;li&gt;Type 3 detection is limited compared to AST-native tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams already using SonarQube that want duplication checks as part of their quality workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. PMD CPD - the copy-paste detector that just works
&lt;/h2&gt;

&lt;p&gt;PMD's Copy/Paste Detector (CPD) has been the go-to standalone duplication checker for over two decades. It is free, fast, reliable, and works with every major build system. If you need a no-frills duplicate code finder that you can add to a CI pipeline in five minutes, CPD is the answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works.&lt;/strong&gt; CPD uses token-based detection. It lexes source files into token streams, then applies the Karp-Rabin algorithm to find matching subsequences. You configure a minimum token count (default: 100), and CPD reports all pairs of code fragments that share at least that many consecutive tokens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What sets it apart.&lt;/strong&gt; Zero dependencies, zero accounts, zero configuration. Download the PMD distribution, run &lt;code&gt;pmd cpd --minimum-tokens 100 --dir src/&lt;/code&gt;, and you get a report. It integrates natively with Maven (&lt;code&gt;mvn pmd:cpd&lt;/code&gt;), Gradle, and Ant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; Java, JavaScript, TypeScript, Python, C/C++, C#, Go, Ruby, Swift, Kotlin, Scala, PHP, Lua, MATLAB, Fortran, and more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free and open source (BSD license).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extremely fast - scans millions of lines in seconds&lt;/li&gt;
&lt;li&gt;No server, no account, no internet connection required&lt;/li&gt;
&lt;li&gt;Native Maven, Gradle, and Ant integration&lt;/li&gt;
&lt;li&gt;Well-documented with 20+ years of stability&lt;/li&gt;
&lt;li&gt;Configurable minimum tokens and output formats (XML, CSV, text)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Token-based only - misses Type 3 and Type 4 clones&lt;/li&gt;
&lt;li&gt;No visualization or trending - just a flat report&lt;/li&gt;
&lt;li&gt;No PR integration or quality gates out of the box&lt;/li&gt;
&lt;li&gt;No web dashboard or historical tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Any team that wants a fast, free, no-nonsense duplication check in CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Simian - commercial token matcher with strict licensing
&lt;/h2&gt;

&lt;p&gt;Simian (Similarity Analyser) is a commercial duplicate code detection tool that focuses on fast, accurate token-based matching. It was popular in the mid-2010s and still has users in enterprise Java and .NET shops.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works.&lt;/strong&gt; Simian uses proprietary token-based matching that the vendor claims is more accurate than CPD for certain edge cases, particularly around multiline string literals and complex expressions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; Java, C#, C/C++, JavaScript, TypeScript, Ruby, Swift, Objective-C, Visual Basic, COBOL, and others.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; $299 for a single developer license, $499 for a site license. One-time purchase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast scanning with low memory footprint&lt;/li&gt;
&lt;li&gt;Good handling of edge cases in .NET and Java code&lt;/li&gt;
&lt;li&gt;One-time license fee rather than subscription&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No longer actively developed - last major update was several years ago&lt;/li&gt;
&lt;li&gt;Token-based only - no Type 3 detection&lt;/li&gt;
&lt;li&gt;No CI/CD integration beyond CLI exit codes&lt;/li&gt;
&lt;li&gt;No web dashboard or PR comments&lt;/li&gt;
&lt;li&gt;PMD CPD provides comparable functionality for free&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Legacy projects already using Simian that do not want to migrate.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. jscpd - the polyglot copy-paste detector
&lt;/h2&gt;

&lt;p&gt;jscpd is a modern, Node.js-based duplicate code detector that supports an impressive range of languages through its tokenizer system. If you work with a polyglot codebase and want a single duplication tool, jscpd is worth considering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works.&lt;/strong&gt; jscpd tokenizes source files using language-specific tokenizers (powered by the Prism syntax highlighter's grammar definitions), then finds matching token sequences using the Rabin-Karp algorithm. It supports a configurable minimum number of tokens and lines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What sets it apart.&lt;/strong&gt; The breadth of language support is exceptional. Because it leverages Prism's grammars, jscpd can tokenize over 150 languages and file formats, including markup languages, configuration files, and even Dockerfiles. It also generates HTML reports with side-by-side clone views.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 150+ including all mainstream programming languages plus markup, configuration, and infrastructure-as-code files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free and open source (MIT license).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Broadest language support of any standalone duplication tool&lt;/li&gt;
&lt;li&gt;Beautiful HTML reports with side-by-side clone visualization&lt;/li&gt;
&lt;li&gt;CI-friendly exit codes and JSON output&lt;/li&gt;
&lt;li&gt;Configurable thresholds per language via &lt;code&gt;.jscpd.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Active open-source project with regular updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Token-based only - no Type 3 or Type 4 detection&lt;/li&gt;
&lt;li&gt;Node.js dependency required&lt;/li&gt;
&lt;li&gt;Slower than PMD CPD on very large codebases&lt;/li&gt;
&lt;li&gt;No server or dashboard for tracking trends over time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Polyglot codebases and teams that want HTML reporting without a server.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. MOSS - academic plagiarism detection for source code
&lt;/h2&gt;

&lt;p&gt;MOSS (Measure Of Software Similarity) is a web-based service from Stanford University designed to detect plagiarism in programming assignments. It is not a typical developer tool, but it excels at detecting code similarity across large sets of submissions - which makes it uniquely useful for certain scenarios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works.&lt;/strong&gt; MOSS uses document fingerprinting with the Winnowing algorithm. You submit a set of source files, and MOSS returns a ranked list of file pairs with the highest similarity, along with a web-based side-by-side view showing the matching regions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What sets it apart.&lt;/strong&gt; MOSS is designed to compare many files against each other simultaneously, which is different from most tools that scan a single codebase. It normalizes code to ignore variable names and whitespace, catching Type 1, 2, and some Type 3 clones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; C, C++, Java, Python, JavaScript, C#, MATLAB, Perl, Haskell, Lisp, Scheme, and others.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free for educational and research use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Excellent at detecting similarity across large file sets&lt;/li&gt;
&lt;li&gt;Web-based visualization with highlighted matching regions&lt;/li&gt;
&lt;li&gt;Handles obfuscation attempts (variable renaming, reordering)&lt;/li&gt;
&lt;li&gt;Trusted and maintained by Stanford for decades&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires uploading code to Stanford's servers - not suitable for proprietary code&lt;/li&gt;
&lt;li&gt;No CI/CD integration&lt;/li&gt;
&lt;li&gt;Web-only interface - no CLI or API for automation&lt;/li&gt;
&lt;li&gt;Designed for academic plagiarism, not production code quality&lt;/li&gt;
&lt;li&gt;Availability depends on Stanford's infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Academic settings and open-source projects where code can be uploaded to an external server.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Duplo - lightweight C/C++ focused detector
&lt;/h2&gt;

&lt;p&gt;Duplo is a simple, lightweight duplicate code detection tool originally designed for C and C++ projects. It takes a minimalist approach - feed it a list of files, and it reports duplicate blocks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works.&lt;/strong&gt; Duplo uses a line-based matching algorithm. It normalizes lines by stripping whitespace and comments, then finds matching sequences of lines above a configurable minimum length. This is simpler than token-based approaches but surprisingly effective for exact and renamed clones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; Technically language-agnostic (line-based matching works on any text), but optimized for C, C++, Java, and C#.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free and open source.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extremely lightweight - single binary, no dependencies&lt;/li&gt;
&lt;li&gt;Fast on large codebases&lt;/li&gt;
&lt;li&gt;Simple to understand and configure&lt;/li&gt;
&lt;li&gt;Works on any text-based language&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Line-based matching is less accurate than token or AST-based detection&lt;/li&gt;
&lt;li&gt;Very basic output - no visualization or HTML reports&lt;/li&gt;
&lt;li&gt;Limited development activity in recent years&lt;/li&gt;
&lt;li&gt;No CI integration beyond exit codes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; C/C++ projects that need a quick, zero-dependency duplication check.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. CloneDR - the research-grade AST clone detector
&lt;/h2&gt;

&lt;p&gt;CloneDR is one of the few tools that uses full AST-based clone detection, developed by Semantic Designs. It parses source code into abstract syntax trees and compares subtrees to find clones - including Type 3 and even some Type 4 clones that token-based tools miss completely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works.&lt;/strong&gt; CloneDR parses source files using language-specific grammars, builds ASTs, and then compares subtrees using a parameterized matching algorithm. It can detect clones where statements have been added, removed, or reordered (Type 3), and in some cases can identify semantically equivalent code with different structure (Type 4).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What sets it apart.&lt;/strong&gt; This is the most thorough clone detection approach available in a commercial tool. CloneDR does not just find copied code - it can suggest a refactored version that extracts the common logic into a shared function with parameters for the varying parts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; Java, C#, C/C++, Python, JavaScript, COBOL, PHP, and others.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Enterprise licensing through Semantic Designs. Contact for quotes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detects Type 3 and some Type 4 clones&lt;/li&gt;
&lt;li&gt;Suggests refactored abstractions for detected clones&lt;/li&gt;
&lt;li&gt;Most thorough detection of any tool in this list&lt;/li&gt;
&lt;li&gt;Handles complex transformations like loop restructuring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expensive enterprise-only licensing&lt;/li&gt;
&lt;li&gt;Slower than token-based tools due to full AST parsing&lt;/li&gt;
&lt;li&gt;Smaller user community - fewer resources and integrations&lt;/li&gt;
&lt;li&gt;No native CI/CD pipeline integration&lt;/li&gt;
&lt;li&gt;Requires language-specific grammars for each supported language&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Organizations serious about eliminating deep structural duplication and willing to invest in thorough analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. CodeAnt AI - duplication detection with AI code review
&lt;/h2&gt;

&lt;p&gt;CodeAnt AI bundles duplicate code detection with its broader AI-powered code review and static analysis platform. It is one of the newer entrants that treats duplication as part of a holistic code quality workflow rather than a standalone feature.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works.&lt;/strong&gt; CodeAnt AI scans repositories connected through GitHub, GitLab, or Bitbucket. Its duplication engine uses a combination of token-based matching and structural analysis to detect Type 1, 2, and 3 clones. Findings appear as PR comments alongside security and quality issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What sets it apart.&lt;/strong&gt; Duplication findings are contextualized with AI-generated explanations. Instead of just pointing out that two blocks match, CodeAnt AI explains why the duplication is problematic and suggests a refactored approach. It also tracks duplication metrics over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 30+ languages including Python, JavaScript, TypeScript, Java, Go, Ruby, PHP, and C#.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free Basic plan for open source. Pro at $24/user/month and Enterprise at $40/user/month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI-powered explanations and refactoring suggestions&lt;/li&gt;
&lt;li&gt;Duplication detection is part of a comprehensive code review platform&lt;/li&gt;
&lt;li&gt;PR-level integration - findings appear as comments on pull requests&lt;/li&gt;
&lt;li&gt;Tracks duplication metrics and trends over time&lt;/li&gt;
&lt;li&gt;SAST, secrets detection, and DORA metrics included&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplication detection is not available as a standalone feature&lt;/li&gt;
&lt;li&gt;Requires connecting your repository to CodeAnt AI's platform&lt;/li&gt;
&lt;li&gt;Newer tool with a smaller community than SonarQube or PMD&lt;/li&gt;
&lt;li&gt;Enterprise pricing adds up for large teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams that want duplication detection bundled with AI code review and static analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Codacy - duplication as part of code quality automation
&lt;/h2&gt;

&lt;p&gt;Codacy includes duplication detection as one of its core code quality checks. Like SonarQube, it bundles duplication analysis with security scanning, code coverage tracking, and quality gates - but as a fully managed cloud service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works.&lt;/strong&gt; Codacy uses PMD CPD and language-specific analyzers under the hood for its duplication detection. It tokenizes code, finds matching sequences, and reports duplicates with links to both locations. Findings appear in the Codacy dashboard and as PR comments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What sets it apart.&lt;/strong&gt; The fully managed experience means zero infrastructure. Connect your GitHub, GitLab, or Bitbucket repository, and duplication analysis starts automatically on every push. Quality gates can enforce duplication thresholds, blocking merges when thresholds are exceeded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 40+ languages through its analyzer ecosystem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free for open source. Pro at $15/user/month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zero-configuration cloud setup&lt;/li&gt;
&lt;li&gt;Quality gates enforce duplication thresholds on PRs&lt;/li&gt;
&lt;li&gt;Duplication trends visible in dashboard over time&lt;/li&gt;
&lt;li&gt;Bundled with SAST, SCA, code coverage, and code quality&lt;/li&gt;
&lt;li&gt;Supports GitHub, GitLab, and Bitbucket&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplication detection relies on PMD CPD - no Type 3 detection&lt;/li&gt;
&lt;li&gt;Cannot run as a standalone CLI tool&lt;/li&gt;
&lt;li&gt;$15/user/month adds up for larger teams&lt;/li&gt;
&lt;li&gt;Less configurable than running PMD CPD directly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams that want a managed code quality platform with duplication checks included.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. DeepSource - fast duplication analysis with Autofix
&lt;/h2&gt;

&lt;p&gt;DeepSource includes duplication detection as part of its static analysis platform and stands out for its speed and low false positive rate. It takes a modern approach to developer experience, with clean UI and actionable findings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works.&lt;/strong&gt; DeepSource uses its own analysis engine that combines token-based and structural techniques. It detects Type 1, 2, and some Type 3 clones. When duplication is found, DeepSource can generate Autofix suggestions that extract duplicated code into shared functions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What sets it apart.&lt;/strong&gt; The Autofix feature for duplication is genuinely useful. Rather than just flagging that code is duplicated, DeepSource proposes a refactored version. Its sub-5% false positive rate also means you do not waste time reviewing findings that are not real issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; Python, JavaScript, TypeScript, Java, Go, Ruby, Rust, C#, Kotlin, Swift, PHP, and others.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free for individual developers and open-source projects. Team plan at $12/user/month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Autofix generates refactored code for duplicated blocks&lt;/li&gt;
&lt;li&gt;Very low false positive rate&lt;/li&gt;
&lt;li&gt;Fast scan times - typically completes in under a minute&lt;/li&gt;
&lt;li&gt;Clean, modern developer experience&lt;/li&gt;
&lt;li&gt;Free tier is generous for individual use&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smaller language coverage than SonarQube or Codacy&lt;/li&gt;
&lt;li&gt;Type 3 detection is limited&lt;/li&gt;
&lt;li&gt;No standalone CLI for duplication-only scanning&lt;/li&gt;
&lt;li&gt;Enterprise features require the paid tier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams that value developer experience and want AI-assisted refactoring of duplicated code.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. IntelliJ IDEA - IDE-native duplicate detection
&lt;/h2&gt;

&lt;p&gt;JetBrains IntelliJ IDEA (and other JetBrains IDEs like PyCharm, WebStorm, and Rider) includes built-in duplicate code detection that runs directly in the editor. This is not a CI/CD tool - it is a developer productivity feature that surfaces duplication while you are actively coding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works.&lt;/strong&gt; IntelliJ's duplicate detection uses AST-based analysis powered by the JetBrains inspection engine. It compares structural elements rather than raw tokens, which enables Type 3 detection where code has been slightly modified. Results appear as editor highlights and in the inspection results panel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What sets it apart.&lt;/strong&gt; The IDE integration means you see duplication immediately as you write code, before you even commit. The refactoring tools built into IntelliJ - Extract Method, Extract Variable, Pull Members Up - work seamlessly with the duplication findings, making it trivial to fix clones on the spot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; Java, Kotlin, Scala, Groovy (IntelliJ), Python (PyCharm), JavaScript/TypeScript (WebStorm), C#/.NET (Rider), PHP (PhpStorm).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Community Edition is free but does not include duplication detection. Ultimate starts at $249/year for individuals, $779/year for organizations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time detection as you write code&lt;/li&gt;
&lt;li&gt;AST-based analysis catches Type 3 clones&lt;/li&gt;
&lt;li&gt;Seamless integration with IntelliJ refactoring tools&lt;/li&gt;
&lt;li&gt;No external tooling or configuration needed&lt;/li&gt;
&lt;li&gt;Cross-module detection within a project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires JetBrains IDE - not available in VS Code or other editors&lt;/li&gt;
&lt;li&gt;Not a CI/CD tool - cannot enforce thresholds on PRs&lt;/li&gt;
&lt;li&gt;Only runs on code currently open in the IDE&lt;/li&gt;
&lt;li&gt;Ultimate license required for full duplication analysis&lt;/li&gt;
&lt;li&gt;No historical tracking or trending&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Individual developers using JetBrains IDEs who want real-time duplication awareness.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Coverity - deep analysis for safety-critical code
&lt;/h2&gt;

&lt;p&gt;Coverity (now part of Black Duck, formerly Synopsys) includes duplication detection as part of its enterprise static analysis platform. Coverity is the standard for safety-critical industries - automotive, aerospace, medical devices, and embedded systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works.&lt;/strong&gt; Coverity performs deep interprocedural analysis that includes clone detection. Its engine builds a comprehensive model of the entire codebase, including call graphs and data flow, which enables it to detect structural clones that simpler tools miss. It focuses on clones that are likely to cause defects - duplicated code with inconsistent error handling or boundary checks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What sets it apart.&lt;/strong&gt; Coverity does not just find duplicated code - it finds duplicated code that is &lt;em&gt;dangerous&lt;/em&gt;. Its defect-oriented approach means it prioritizes clones where one copy has been patched but others have not, which is exactly the pattern that causes real-world bugs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; C, C++, Java, C#, JavaScript, TypeScript, Python, Ruby, Go, Kotlin, Swift, and others.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Enterprise-only. Typically $50,000+ per year depending on codebase size and seats.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Defect-focused duplication detection - finds clones that cause bugs&lt;/li&gt;
&lt;li&gt;Deep interprocedural analysis catches complex structural clones&lt;/li&gt;
&lt;li&gt;Industry standard for safety-critical code (ISO 26262, DO-178C)&lt;/li&gt;
&lt;li&gt;Finds inconsistently patched clones that other tools miss&lt;/li&gt;
&lt;li&gt;Comprehensive reporting for compliance requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extremely expensive - not practical for small teams&lt;/li&gt;
&lt;li&gt;Slow scan times due to deep analysis&lt;/li&gt;
&lt;li&gt;Complex deployment and configuration&lt;/li&gt;
&lt;li&gt;Overkill for web applications or non-critical software&lt;/li&gt;
&lt;li&gt;No free tier or community edition&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Enterprise teams working on safety-critical software where finding dangerous clones is more important than finding all clones.&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Semgrep - pattern-based duplicate detection with custom rules
&lt;/h2&gt;

&lt;p&gt;Semgrep takes a different approach to duplication. Rather than scanning for arbitrary matching code blocks, Semgrep lets you define patterns that match specific types of duplication in your codebase. This is not traditional clone detection - it is targeted pattern matching that catches the duplication patterns that matter most to your team.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works.&lt;/strong&gt; You write Semgrep rules using a pattern syntax that matches code structure rather than exact text. For example, you can write a rule that detects when the same error handling pattern is duplicated across multiple catch blocks, or when identical validation logic appears in multiple API endpoints. Semgrep matches against the AST, so it catches renamed variables and reformatted code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What sets it apart.&lt;/strong&gt; The custom rule approach means you focus on the duplication that actually causes problems in your codebase. Instead of a noisy report showing every duplicated three-line block, you get targeted findings for the specific patterns you care about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 30+ including Python, JavaScript, TypeScript, Java, Go, Ruby, C, C++, Rust, PHP, Kotlin, Swift, and more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Open-source CLI is free (LGPL-2.1). Team tier available for PR integration, and enterprise pricing for advanced features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom rules target the specific duplication patterns that matter&lt;/li&gt;
&lt;li&gt;AST-based matching catches renamed and reformatted clones&lt;/li&gt;
&lt;li&gt;Extremely fast - scans most codebases in seconds&lt;/li&gt;
&lt;li&gt;Huge community rule library with 3,000+ pre-built rules&lt;/li&gt;
&lt;li&gt;Free for commercial use and CI/CD integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not a traditional clone detector - requires writing rules for specific patterns&lt;/li&gt;
&lt;li&gt;Will not generate a comprehensive duplication report like PMD CPD&lt;/li&gt;
&lt;li&gt;No built-in duplication percentage metric&lt;/li&gt;
&lt;li&gt;Requires learning Semgrep's pattern syntax&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams that know what duplication patterns to target and want precise, low-noise detection.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to choose the right duplicate code checker
&lt;/h2&gt;

&lt;p&gt;The right tool depends on what you need:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For a quick CLI scan with no setup,&lt;/strong&gt; use PMD CPD. It is free, fast, and integrates with every build tool. Run &lt;code&gt;pmd cpd --minimum-tokens 75 --dir src/&lt;/code&gt; and you have a report in seconds. If you work with many languages, jscpd is the better choice for its broader tokenizer support.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For CI/CD enforcement,&lt;/strong&gt; SonarQube, Codacy, or DeepSource give you quality gates that block PRs when duplication thresholds are exceeded. Codacy and DeepSource are fully managed, while SonarQube requires self-hosting (unless you use SonarCloud).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For IDE-level awareness,&lt;/strong&gt; IntelliJ IDEA's built-in duplication detection catches clones as you type. This prevents duplication before it is committed rather than catching it after the fact.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For deep structural analysis,&lt;/strong&gt; CloneDR and Coverity detect Type 3 and Type 4 clones that token-based tools miss entirely. These are expensive options but essential for safety-critical codebases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For AI-assisted refactoring,&lt;/strong&gt; CodeAnt AI and DeepSource go beyond detection by suggesting how to refactor duplicated code. This bridges the gap between finding duplication and actually fixing it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For targeted pattern matching,&lt;/strong&gt; Semgrep lets you define rules for the specific duplication patterns that cause problems in your codebase. This is the lowest-noise approach but requires upfront effort to write rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up duplicate code detection in CI
&lt;/h2&gt;

&lt;p&gt;Here is a practical example of adding duplication checks to a GitHub Actions pipeline using PMD CPD:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Duplication Check&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;cpd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Download PMD&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;wget https://github.com/pmd/pmd/releases/download/pmd_releases%2F7.9.0/pmd-dist-7.9.0-bin.zip&lt;/span&gt;
          &lt;span class="s"&gt;unzip pmd-dist-7.9.0-bin.zip&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run CPD&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;./pmd-bin-7.9.0/bin/pmd cpd \&lt;/span&gt;
            &lt;span class="s"&gt;--minimum-tokens 100 \&lt;/span&gt;
            &lt;span class="s"&gt;--dir src/ \&lt;/span&gt;
            &lt;span class="s"&gt;--format xml \&lt;/span&gt;
            &lt;span class="s"&gt;--fail-on-violation true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For jscpd, the setup is even simpler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Duplication Check&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;jscpd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx jscpd src/ --threshold 5 --reporters console&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--threshold 5&lt;/code&gt; flag fails the check when duplication exceeds 5% of total lines.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;Duplicate code detection is a solved problem at the tool level. PMD CPD and jscpd are free, fast, and effective for token-based detection. SonarQube, Codacy, and DeepSource bundle duplication checks into broader quality platforms. CloneDR and Coverity provide deep structural analysis for teams that need it.&lt;/p&gt;

&lt;p&gt;The unsolved problem is actually fixing duplication once you find it. That is where the newer tools - CodeAnt AI with its AI-powered suggestions, DeepSource with Autofix, and IntelliJ with its refactoring tools - are pushing the field forward. Detection without a path to remediation just creates a backlog of tech debt that nobody addresses.&lt;/p&gt;

&lt;p&gt;My recommendation for most teams: start with PMD CPD or jscpd in CI to establish a baseline and prevent new duplication. If you are already using SonarQube, Codacy, or DeepSource, enable their duplication checks and set quality gates. If you are working on safety-critical software, invest in Coverity's defect-focused approach. And regardless of what you use in CI, enable IntelliJ's duplication detection in your IDE - catching clones before they are committed is always cheaper than catching them after.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is the best free duplicate code checker?
&lt;/h3&gt;

&lt;p&gt;PMD CPD is the best free duplicate code checker for most teams. It supports 20+ languages, detects Type 1 and Type 2 clones, integrates with every major build tool, and runs locally without any account or server. For JavaScript and TypeScript projects, jscpd is an excellent alternative with built-in HTML reporting and CI-friendly exit codes. SonarQube Community Build also includes copy-paste detection at no cost, though it requires a self-hosted server.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are the four types of code clones?
&lt;/h3&gt;

&lt;p&gt;Type 1 clones are exact copies with only whitespace and comment differences. Type 2 clones are syntactically identical but with renamed variables, changed types, or modified literals. Type 3 clones are near-miss copies where statements have been added, removed, or reordered. Type 4 clones are semantically equivalent but syntactically different - two functions that produce the same output using completely different logic. Most tools detect Type 1 and 2 reliably. Type 3 detection requires AST-based analysis. Type 4 detection remains a research problem, though AI-powered tools are making progress.&lt;/p&gt;

&lt;h3&gt;
  
  
  How much code duplication is acceptable?
&lt;/h3&gt;

&lt;p&gt;Most industry benchmarks consider less than 3-5% duplication acceptable for a healthy codebase. SonarQube's default quality gate flags code with more than 3% duplication on new code. However, context matters - some duplication is intentional and acceptable, such as test setup code or generated files. The key metric is whether duplicated code is actively maintained in multiple places, creating a risk of inconsistent changes. Zero duplication is not a realistic or even desirable target.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the DRY principle and why does it matter?
&lt;/h3&gt;

&lt;p&gt;DRY stands for Don't Repeat Yourself, a software engineering principle stating that every piece of knowledge should have a single, authoritative representation in a system. Violating DRY by copy-pasting code creates maintenance burden - when a bug is fixed in one copy, all other copies must be found and updated. Studies show that inconsistent changes to cloned code account for a significant percentage of bugs in large codebases. DRY is not about eliminating all similar-looking code - it is about ensuring that business logic and domain knowledge are not scattered across multiple locations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can duplicate code checkers run in CI/CD pipelines?
&lt;/h3&gt;

&lt;p&gt;Yes, most modern duplicate code checkers integrate with CI/CD pipelines. PMD CPD, jscpd, and Duplo run as CLI tools that return non-zero exit codes when duplication thresholds are exceeded, making them easy to add to any pipeline. SonarQube, Codacy, DeepSource, and CodeAnt AI provide native GitHub Actions and GitLab CI integrations that comment duplication findings directly on pull requests. The key is configuring appropriate thresholds so the check catches meaningful duplication without blocking every PR over minor similarities.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the difference between token-based and AST-based clone detection?
&lt;/h3&gt;

&lt;p&gt;Token-based detection (used by PMD CPD, Simian, and jscpd) breaks source code into a stream of tokens and finds matching sequences. It is fast and language-agnostic but only reliably detects Type 1 and Type 2 clones. AST-based detection (used by CloneDR, SonarQube, and DeepSource) parses code into abstract syntax trees and compares subtrees, which catches Type 3 clones where code has been modified or reordered. AST-based tools are slower but more accurate for detecting near-miss duplicates that token matching misses.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://aicodereview.cc/blog/best-duplicate-code-checker-tools/" rel="noopener noreferrer"&gt;aicodereview.cc&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>ai</category>
      <category>programming</category>
      <category>tools</category>
    </item>
    <item>
      <title>12 Best Code Test Coverage Tools in 2026 - Comprehensive Guide</title>
      <dc:creator>Rahul Singh</dc:creator>
      <pubDate>Fri, 10 Apr 2026 22:30:00 +0000</pubDate>
      <link>https://dev.to/rahulxsingh/12-best-code-test-coverage-tools-in-2026-comprehensive-guide-3kh3</link>
      <guid>https://dev.to/rahulxsingh/12-best-code-test-coverage-tools-in-2026-comprehensive-guide-3kh3</guid>
      <description>&lt;h2&gt;
  
  
  Why code test coverage matters in 2026
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Code coverage is the most widely used metric for measuring test quality.&lt;/strong&gt; It tells you what percentage of your codebase is actually exercised when your test suite runs - and more importantly, it reveals which parts of your code have no tests at all.&lt;/p&gt;

&lt;p&gt;Without coverage measurement, teams are guessing about test effectiveness. A project might have 500 tests that all pass while leaving critical business logic completely untested. Coverage tools eliminate this guessing by generating precise reports showing which lines, branches, and functions were hit during test execution.&lt;/p&gt;

&lt;p&gt;The tooling landscape for code coverage has evolved significantly. Language-specific instrumentation tools like Istanbul and JaCoCo remain the foundation, but modern platforms now layer on PR-level reporting, historical trend analysis, coverage gates that block merges below a threshold, and integration with broader code quality workflows.&lt;/p&gt;

&lt;p&gt;This guide compares 12 code test coverage tools across language support, CI integration, reporting capabilities, and pricing. Whether you need a free open source solution for a single-language project or an enterprise platform that aggregates coverage across a polyglot monorepo, you will find the right fit here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick comparison table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Languages&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;CI Integration&lt;/th&gt;
&lt;th&gt;Free Tier&lt;/th&gt;
&lt;th&gt;Pricing&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Istanbul/nyc&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;JavaScript, TypeScript&lt;/td&gt;
&lt;td&gt;Instrumentation&lt;/td&gt;
&lt;td&gt;Any CI&lt;/td&gt;
&lt;td&gt;Fully free&lt;/td&gt;
&lt;td&gt;Free (OSS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;JaCoCo&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Java, Kotlin, Scala&lt;/td&gt;
&lt;td&gt;Instrumentation&lt;/td&gt;
&lt;td&gt;Any CI&lt;/td&gt;
&lt;td&gt;Fully free&lt;/td&gt;
&lt;td&gt;Free (OSS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Coverage.py&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;Instrumentation&lt;/td&gt;
&lt;td&gt;Any CI&lt;/td&gt;
&lt;td&gt;Fully free&lt;/td&gt;
&lt;td&gt;Free (OSS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Codecov&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;30+ (via report upload)&lt;/td&gt;
&lt;td&gt;Reporting platform&lt;/td&gt;
&lt;td&gt;GitHub, GitLab, Bitbucket&lt;/td&gt;
&lt;td&gt;Free for OSS&lt;/td&gt;
&lt;td&gt;From $10/user/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Coveralls&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;22+ (via report upload)&lt;/td&gt;
&lt;td&gt;Reporting platform&lt;/td&gt;
&lt;td&gt;GitHub, GitLab, Bitbucket&lt;/td&gt;
&lt;td&gt;Free for OSS&lt;/td&gt;
&lt;td&gt;From $5/user/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SonarQube&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;35+&lt;/td&gt;
&lt;td&gt;Quality platform&lt;/td&gt;
&lt;td&gt;GitHub, GitLab, Bitbucket, Azure&lt;/td&gt;
&lt;td&gt;Community free&lt;/td&gt;
&lt;td&gt;From $2,500/yr&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DeepSource&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;Quality platform&lt;/td&gt;
&lt;td&gt;GitHub, GitLab, Bitbucket&lt;/td&gt;
&lt;td&gt;Free for OSS&lt;/td&gt;
&lt;td&gt;From $12/user/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Codacy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;49&lt;/td&gt;
&lt;td&gt;Quality platform&lt;/td&gt;
&lt;td&gt;GitHub, GitLab, Bitbucket&lt;/td&gt;
&lt;td&gt;Free for OSS&lt;/td&gt;
&lt;td&gt;From $15/user/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;dotCover&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;C#, .NET, VB.NET&lt;/td&gt;
&lt;td&gt;Instrumentation&lt;/td&gt;
&lt;td&gt;Any CI&lt;/td&gt;
&lt;td&gt;Free (CLI)&lt;/td&gt;
&lt;td&gt;From $15.90/mo (IDE)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OpenCover&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;.NET Framework&lt;/td&gt;
&lt;td&gt;Instrumentation&lt;/td&gt;
&lt;td&gt;Any CI&lt;/td&gt;
&lt;td&gt;Fully free&lt;/td&gt;
&lt;td&gt;Free (OSS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bullseye Testing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;C, C++&lt;/td&gt;
&lt;td&gt;Instrumentation&lt;/td&gt;
&lt;td&gt;Any CI&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;From $800/seat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;gcov/lcov&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;C, C++, Fortran&lt;/td&gt;
&lt;td&gt;Instrumentation&lt;/td&gt;
&lt;td&gt;Any CI&lt;/td&gt;
&lt;td&gt;Fully free&lt;/td&gt;
&lt;td&gt;Free (OSS)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  1. Istanbul/nyc - best for JavaScript and TypeScript
&lt;/h2&gt;

&lt;p&gt;Istanbul is the standard code coverage tool for the JavaScript ecosystem. Nearly every major JavaScript project - from React and Next.js to Express and NestJS - uses Istanbul for coverage measurement. The &lt;strong&gt;nyc&lt;/strong&gt; command-line tool is the most common way to run Istanbul, wrapping your test runner and instrumenting code on the fly.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it does
&lt;/h3&gt;

&lt;p&gt;Istanbul instruments your JavaScript and TypeScript source code to track which lines, branches, functions, and statements execute during tests. It works by inserting counters into your code at build time or runtime, then collecting execution data when tests run. The result is a detailed report showing exactly which code paths were covered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Language support
&lt;/h3&gt;

&lt;p&gt;JavaScript, TypeScript, and any language that transpiles to JavaScript (CoffeeScript, Flow). Istanbul handles ES modules, CommonJS, and JSX/TSX syntax natively. If you use Babel, webpack, or Vite, Istanbul integrates through their plugin systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Four coverage metrics&lt;/strong&gt; - line, branch, function, and statement coverage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple report formats&lt;/strong&gt; - HTML, LCOV, Cobertura XML, text, JSON, and clover&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in threshold enforcement&lt;/strong&gt; - fail CI when coverage drops below a configured percentage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Source map support&lt;/strong&gt; - accurate coverage for transpiled TypeScript and Babel code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Merge support&lt;/strong&gt; - combine reports from multiple test runs (unit, integration, e2e) into a single report&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jest integration&lt;/strong&gt; - Jest uses Istanbul internally, so &lt;code&gt;--coverage&lt;/code&gt; flag works out of the box&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CI integration
&lt;/h3&gt;

&lt;p&gt;Istanbul works in any CI environment. Generate an LCOV report and upload it to Codecov, Coveralls, or SonarQube for PR-level feedback. For GitHub Actions, a typical workflow runs &lt;code&gt;nyc mocha&lt;/code&gt; or &lt;code&gt;jest --coverage&lt;/code&gt;, then uploads the resulting &lt;code&gt;coverage/lcov.info&lt;/code&gt; file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Completely free and open source under the BSD-2-Clause license. No paid tiers or enterprise editions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;De facto standard for JavaScript coverage - virtually every JS testing tool supports it&lt;/li&gt;
&lt;li&gt;Zero-config with Jest (built in) and minimal config with Mocha, Vitest, and AVA&lt;/li&gt;
&lt;li&gt;Excellent source map support for TypeScript projects&lt;/li&gt;
&lt;li&gt;Active maintenance with regular updates&lt;/li&gt;
&lt;li&gt;Rich report formats suitable for any downstream tool&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Limited to the JavaScript ecosystem - not useful for polyglot projects on its own&lt;/li&gt;
&lt;li&gt;nyc configuration can be tricky for complex monorepo setups with multiple test runners&lt;/li&gt;
&lt;li&gt;No built-in dashboard or historical tracking - you need a reporting service for that&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. JaCoCo - best for Java, Kotlin, and Scala
&lt;/h2&gt;

&lt;p&gt;JaCoCo (Java Code Coverage) is the dominant coverage tool for JVM languages. It is used by the vast majority of Java projects in production, from small Spring Boot applications to enterprise monoliths with millions of lines of code.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it does
&lt;/h3&gt;

&lt;p&gt;JaCoCo uses bytecode instrumentation to measure coverage without modifying source code. It attaches as a Java agent during test execution, instruments class files on the fly, and records which instructions and branches were executed. This approach means JaCoCo works with any JVM language that compiles to bytecode.&lt;/p&gt;

&lt;h3&gt;
  
  
  Language support
&lt;/h3&gt;

&lt;p&gt;Java, Kotlin, Scala, Groovy, and any JVM language. Coverage is measured at the bytecode level, so source language does not matter as long as it compiles to JVM bytecode.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bytecode-level instrumentation&lt;/strong&gt; - no source code modification required&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Line, branch, instruction, and cyclomatic complexity&lt;/strong&gt; coverage metrics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maven and Gradle plugins&lt;/strong&gt; - first-class build tool integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Report merging&lt;/strong&gt; - aggregate coverage from unit tests, integration tests, and different modules&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTML, XML, and CSV reports&lt;/strong&gt; - the XML format integrates with SonarQube, Codecov, and most CI tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exclusion filters&lt;/strong&gt; - skip generated code, DTOs, or specific packages from coverage calculation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CI integration
&lt;/h3&gt;

&lt;p&gt;JaCoCo integrates natively with Maven (&lt;code&gt;jacoco-maven-plugin&lt;/code&gt;) and Gradle (&lt;code&gt;jacoco&lt;/code&gt; plugin). Both produce XML reports that upload directly to Codecov, Coveralls, or SonarQube. Jenkins has a dedicated JaCoCo plugin for trend visualization.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Completely free and open source under the Eclipse Public License 2.0.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Industry standard for JVM coverage - supported by every Java CI/CD tool&lt;/li&gt;
&lt;li&gt;Bytecode instrumentation means zero source code changes&lt;/li&gt;
&lt;li&gt;Excellent Maven and Gradle integration with minimal configuration&lt;/li&gt;
&lt;li&gt;Accurate branch coverage even for complex conditional logic&lt;/li&gt;
&lt;li&gt;Merges coverage from multiple test phases (unit + integration)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;JVM-only - not applicable outside the Java ecosystem&lt;/li&gt;
&lt;li&gt;HTML reports are functional but visually dated&lt;/li&gt;
&lt;li&gt;Kotlin inline functions can produce confusing coverage results due to bytecode differences&lt;/li&gt;
&lt;li&gt;Configuration for multi-module projects requires careful setup&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Coverage.py - best for Python
&lt;/h2&gt;

&lt;p&gt;Coverage.py is the standard coverage tool for Python. Created by Ned Batchelder and actively maintained for over 15 years, it is used by nearly every Python project that measures test coverage.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it does
&lt;/h3&gt;

&lt;p&gt;Coverage.py hooks into Python's tracing infrastructure to monitor which lines of Python source code execute during test runs. It supports both line and branch coverage measurement and produces reports in multiple formats.&lt;/p&gt;

&lt;h3&gt;
  
  
  Language support
&lt;/h3&gt;

&lt;p&gt;Python only (CPython and PyPy). Supports Python 3.9 through 3.13+.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Line and branch coverage&lt;/strong&gt; with accurate source mapping&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pytest integration&lt;/strong&gt; via &lt;code&gt;pytest-cov&lt;/code&gt; plugin - add &lt;code&gt;--cov&lt;/code&gt; flag to any pytest run&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple report formats&lt;/strong&gt; - terminal, HTML, XML (Cobertura), JSON, and LCOV&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic context&lt;/strong&gt; tracking - see which test covered each line&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Combining reports&lt;/strong&gt; from parallel test runs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration via pyproject.toml&lt;/strong&gt; - modern Python project configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CI integration
&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;pytest --cov=mypackage --cov-report=xml&lt;/code&gt; to generate a Cobertura XML report, then upload to Codecov or Coveralls. Works in any CI environment. SonarQube's Python analysis also ingests Coverage.py reports.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Completely free and open source under the Apache 2.0 license.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;De facto standard for Python coverage - universally supported&lt;/li&gt;
&lt;li&gt;Excellent pytest integration through pytest-cov&lt;/li&gt;
&lt;li&gt;Branch coverage catches untested conditional paths&lt;/li&gt;
&lt;li&gt;Dynamic context feature links each line to the test that covered it&lt;/li&gt;
&lt;li&gt;Active, stable maintenance with regular Python version support updates&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Python only&lt;/li&gt;
&lt;li&gt;Branch coverage can report confusing results for multiline expressions&lt;/li&gt;
&lt;li&gt;No built-in dashboard or trend tracking&lt;/li&gt;
&lt;li&gt;Does not measure coverage for C extensions in Python packages&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Codecov - best coverage reporting platform
&lt;/h2&gt;

&lt;p&gt;Codecov is the most popular dedicated coverage reporting platform. It does not instrument code itself - instead, it ingests coverage reports from tools like Istanbul, JaCoCo, and Coverage.py, then provides rich visualization, PR integration, and historical tracking.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it does
&lt;/h3&gt;

&lt;p&gt;Codecov receives coverage reports uploaded from your CI pipeline, processes them, and provides a centralized dashboard showing coverage metrics, trends over time, and per-PR coverage impact. Its most valuable feature is the PR comment that shows exactly how a pull request changes coverage - which new lines are covered, which are not, and whether overall coverage improved or regressed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Language support
&lt;/h3&gt;

&lt;p&gt;Codecov is language-agnostic. It supports any language that produces coverage reports in standard formats: LCOV, Cobertura XML, JaCoCo XML, clover, gcov, and 20+ other formats. This means it works with JavaScript, Python, Java, Go, Ruby, C/C++, Rust, PHP, Swift, and virtually any other language.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PR comments&lt;/strong&gt; showing coverage diff, new lines covered/uncovered, and overall impact&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coverage status checks&lt;/strong&gt; - block merges when coverage drops below threshold&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flags&lt;/strong&gt; - separate coverage by test type (unit, integration, e2e) or component&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Carryforward flags&lt;/strong&gt; - avoid coverage drops when only part of a monorepo is tested&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sunburst and grid visualizations&lt;/strong&gt; for identifying coverage gaps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Component-level coverage&lt;/strong&gt; for monorepos with multiple services&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub, GitLab, and Bitbucket&lt;/strong&gt; native integration&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CI integration
&lt;/h3&gt;

&lt;p&gt;Codecov provides a GitHub Action, GitLab CI template, and a universal CLI uploader. Upload is typically a single line added to your CI workflow. The Codecov uploader auto-detects report formats and handles merging when multiple reports are uploaded per commit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free&lt;/strong&gt; for public/open source repositories (unlimited users)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer&lt;/strong&gt; - $10/user/month for private repos (up to 5 users)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team&lt;/strong&gt; - $15/user/month with advanced features&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise&lt;/strong&gt; - custom pricing with self-hosted option, SSO, and audit logs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Best-in-class PR integration with clear, actionable coverage diffs&lt;/li&gt;
&lt;li&gt;Language-agnostic - works with any coverage format&lt;/li&gt;
&lt;li&gt;Carryforward flags solve the monorepo coverage problem elegantly&lt;/li&gt;
&lt;li&gt;Free for open source projects&lt;/li&gt;
&lt;li&gt;Fast upload and processing - results typically appear within 60 seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No code instrumentation - you still need a language-specific tool to generate reports&lt;/li&gt;
&lt;li&gt;Paid plans can get expensive for large teams&lt;/li&gt;
&lt;li&gt;Occasional report processing delays during peak hours&lt;/li&gt;
&lt;li&gt;The UI can be overwhelming for teams that just want basic coverage numbers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Coveralls - lightweight coverage reporting
&lt;/h2&gt;

&lt;p&gt;Coveralls is a coverage reporting platform similar to Codecov but with a simpler, more focused feature set. It is popular among open source projects and small teams that want straightforward coverage tracking without the complexity of a full platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it does
&lt;/h3&gt;

&lt;p&gt;Like Codecov, Coveralls receives coverage reports from your CI pipeline and provides dashboards, PR comments, and historical tracking. It focuses on simplicity - showing you coverage percentages, trends, and file-level breakdowns without the advanced features that larger platforms offer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Language support
&lt;/h3&gt;

&lt;p&gt;Language-agnostic through report ingestion. Supports LCOV, Cobertura XML, JaCoCo XML, SimpleCov (Ruby), and other standard formats. Official libraries exist for Ruby, Python, JavaScript, PHP, Go, Java, and .NET.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PR comments&lt;/strong&gt; with coverage change summary&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Badge generation&lt;/strong&gt; for README files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Historical coverage tracking&lt;/strong&gt; with trend graphs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File-level coverage&lt;/strong&gt; breakdown with source highlighting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub, GitLab, and Bitbucket&lt;/strong&gt; integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallel build support&lt;/strong&gt; for merging reports from matrix CI runs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CI integration
&lt;/h3&gt;

&lt;p&gt;Coveralls provides language-specific reporter packages (e.g., &lt;code&gt;coveralls&lt;/code&gt; npm package, &lt;code&gt;coveralls&lt;/code&gt; Python package) and a universal GitHub Action. Most integrations require two to three lines of CI configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free&lt;/strong&gt; for public/open source repositories&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pro&lt;/strong&gt; - from $5/user/month for private repos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise&lt;/strong&gt; - custom pricing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Simple and focused - easy to set up and understand&lt;/li&gt;
&lt;li&gt;Generous free tier for open source&lt;/li&gt;
&lt;li&gt;Lower price point than Codecov for small teams&lt;/li&gt;
&lt;li&gt;Clean, readable PR comments&lt;/li&gt;
&lt;li&gt;Good official language-specific reporter packages&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Fewer advanced features than Codecov (no flags, no component coverage, limited monorepo support)&lt;/li&gt;
&lt;li&gt;Dashboard is basic compared to alternatives&lt;/li&gt;
&lt;li&gt;Less frequent feature updates than Codecov&lt;/li&gt;
&lt;li&gt;No self-hosted option for enterprise environments&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. SonarQube - best for unified quality and coverage
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/sonarqube"&gt;SonarQube&lt;/a&gt; is a comprehensive code quality platform that includes coverage tracking as part of its broader analysis. It does not instrument code directly - instead, it imports coverage reports from language-specific tools and presents them alongside code quality, security, and duplication findings.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it does
&lt;/h3&gt;

&lt;p&gt;SonarQube ingests coverage data from tools like JaCoCo, Istanbul, Coverage.py, and gcov, then integrates that data into its quality dashboard. Coverage becomes one dimension of the overall "Quality Gate" - a pass/fail check that can enforce minimum coverage on new code, maximum duplication, zero critical bugs, and other quality thresholds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Language support
&lt;/h3&gt;

&lt;p&gt;SonarQube supports coverage import for 35+ languages. It accepts standard coverage formats (LCOV, Cobertura, JaCoCo, etc.) and maps coverage data to its own analysis results.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quality Gates&lt;/strong&gt; - enforce minimum coverage on new code alongside other quality metrics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coverage on new code&lt;/strong&gt; - separate metric for recently added/changed code vs. overall coverage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pull request decoration&lt;/strong&gt; with inline coverage annotations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Historical dashboards&lt;/strong&gt; showing coverage trends over weeks and months&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portfolio-level views&lt;/strong&gt; for tracking coverage across multiple projects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security hotspot detection&lt;/strong&gt; combined with coverage gaps to prioritize testing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CI integration
&lt;/h3&gt;

&lt;p&gt;SonarQube uses the SonarScanner CLI or build-tool plugins (Maven, Gradle, .NET) to upload analysis results. Coverage reports are passed as analysis parameters. Native integration with GitHub Actions, GitLab CI, Azure DevOps, Jenkins, and Bitbucket Pipelines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Community Build&lt;/strong&gt; - free and open source (limited features)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer Edition&lt;/strong&gt; - from $2,500/year (branch analysis, PR decoration)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise Edition&lt;/strong&gt; - from $22,000/year (portfolio management, SAST)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Center Edition&lt;/strong&gt; - from $130,000/year (high availability)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Coverage is part of a comprehensive quality management platform&lt;/li&gt;
&lt;li&gt;Quality Gates enforce coverage standards as part of a broader quality strategy&lt;/li&gt;
&lt;li&gt;Excellent "coverage on new code" metric prevents existing technical debt from blocking progress&lt;/li&gt;
&lt;li&gt;Wide language support across a single dashboard&lt;/li&gt;
&lt;li&gt;Strong enterprise adoption with compliance reporting&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Does not generate coverage data - you need language-specific tools first&lt;/li&gt;
&lt;li&gt;Community Edition lacks PR decoration and branch analysis&lt;/li&gt;
&lt;li&gt;Self-hosted infrastructure adds operational overhead&lt;/li&gt;
&lt;li&gt;Can be overkill if you only need coverage tracking&lt;/li&gt;
&lt;li&gt;Configuration is more complex than dedicated coverage tools&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. DeepSource - best for AI-powered coverage insights
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/deepsource"&gt;DeepSource&lt;/a&gt; is a code quality platform that combines static analysis with coverage tracking and AI-powered recommendations. Its coverage features focus on identifying not just what is uncovered, but what should be tested first.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it does
&lt;/h3&gt;

&lt;p&gt;DeepSource imports coverage data and combines it with its static analysis findings to surface high-risk uncovered code. Instead of just showing a coverage percentage, it highlights functions with complex logic, security-sensitive code, and frequently changed files that lack test coverage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Language support
&lt;/h3&gt;

&lt;p&gt;Python, JavaScript, TypeScript, Go, Java, Ruby, Rust, Kotlin, Scala, Swift, C#, PHP, and more (16 languages total for static analysis, coverage import for most major languages).&lt;/p&gt;

&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Risk-prioritized coverage gaps&lt;/strong&gt; - highlights uncovered code that is most likely to cause bugs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coverage tracking&lt;/strong&gt; with historical trends and per-PR reporting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Autofix suggestions&lt;/strong&gt; - can generate test stubs for uncovered functions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration with static analysis&lt;/strong&gt; findings for unified quality view&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sub-5% false positive rate&lt;/strong&gt; on static analysis findings&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CI integration
&lt;/h3&gt;

&lt;p&gt;DeepSource connects via GitHub, GitLab, or Bitbucket app. Coverage reports are uploaded using the DeepSource CLI. Supports LCOV, Cobertura, JaCoCo, and other standard formats.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free&lt;/strong&gt; for open source and individual developers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team&lt;/strong&gt; - $12/user/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise&lt;/strong&gt; - custom pricing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Intelligent prioritization of coverage gaps based on code risk&lt;/li&gt;
&lt;li&gt;Clean, modern dashboard that developers actually use&lt;/li&gt;
&lt;li&gt;Low false positive rate on complementary static analysis&lt;/li&gt;
&lt;li&gt;Competitive pricing compared to alternatives&lt;/li&gt;
&lt;li&gt;Fast setup with minimal configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Smaller community than SonarQube or Codecov&lt;/li&gt;
&lt;li&gt;Fewer coverage-specific features than dedicated tools like Codecov&lt;/li&gt;
&lt;li&gt;Language support is narrower than some competitors&lt;/li&gt;
&lt;li&gt;Coverage insights depend on also running DeepSource's static analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. Codacy - best for coverage plus code quality in one platform
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/codacy"&gt;Codacy&lt;/a&gt; combines code coverage tracking with static analysis, security scanning, and code duplication detection in a single platform. It is particularly strong for teams that want a unified quality dashboard without managing multiple tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it does
&lt;/h3&gt;

&lt;p&gt;Codacy imports coverage data from your test runs and presents it alongside code quality findings. It tracks coverage per file, per pull request, and over time, with configurable quality gates that can enforce minimum coverage thresholds on new code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Language support
&lt;/h3&gt;

&lt;p&gt;Codacy supports 49 programming languages for code analysis. Coverage import is available for any language that produces standard report formats (LCOV, Cobertura, JaCoCo, OpenCover, dotCover, PHPUnit, etc.).&lt;/p&gt;

&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unified quality dashboard&lt;/strong&gt; - coverage, code quality, security, and duplication in one view&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PR-level coverage&lt;/strong&gt; with inline annotations showing uncovered new lines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality gates&lt;/strong&gt; enforcing coverage thresholds alongside other quality standards&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organization-level reporting&lt;/strong&gt; across all repositories&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coverage diff&lt;/strong&gt; showing impact of each pull request&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;49 language support&lt;/strong&gt; for the broadest polyglot coverage&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CI integration
&lt;/h3&gt;

&lt;p&gt;Codacy provides a coverage reporter CLI and a GitHub Action. Upload coverage reports from any CI system. Native integration with GitHub, GitLab, and Bitbucket.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free&lt;/strong&gt; for open source projects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pro&lt;/strong&gt; - $15/user/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Business&lt;/strong&gt; - custom pricing with SAST, DAST, and advanced features&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Widest language support at 49 languages&lt;/li&gt;
&lt;li&gt;All-in-one platform reduces tool sprawl&lt;/li&gt;
&lt;li&gt;Good PR integration with coverage diff annotations&lt;/li&gt;
&lt;li&gt;Free tier available for open source&lt;/li&gt;
&lt;li&gt;Supports a wide variety of coverage report formats&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Coverage features are not as deep as dedicated tools like Codecov&lt;/li&gt;
&lt;li&gt;Dashboard can be slow with very large repositories&lt;/li&gt;
&lt;li&gt;Some advanced coverage features (component-level tracking) are missing&lt;/li&gt;
&lt;li&gt;Quality gate configuration requires navigating multiple settings pages&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  9. dotCover - best for .NET and C
&lt;/h2&gt;

&lt;p&gt;JetBrains dotCover is a coverage tool designed specifically for the .NET ecosystem. It integrates with JetBrains Rider and Visual Studio, providing inline coverage visualization directly in the IDE.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it does
&lt;/h3&gt;

&lt;p&gt;dotCover instruments .NET assemblies to track which lines and branches execute during test runs. It provides both an IDE-integrated experience (highlighting covered and uncovered lines in the editor) and a command-line tool for CI pipelines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Language support
&lt;/h3&gt;

&lt;p&gt;C#, VB.NET, F#, and any .NET language. Supports .NET Framework, .NET Core, and .NET 6/7/8/9+. Works with NUnit, xUnit, MSTest, and other .NET test frameworks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IDE integration&lt;/strong&gt; - inline coverage highlighting in Rider and Visual Studio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Continuous testing&lt;/strong&gt; - re-runs affected tests automatically when you save&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coverage filters&lt;/strong&gt; - include or exclude assemblies, namespaces, and types&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snapshot comparison&lt;/strong&gt; - compare coverage between runs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple report formats&lt;/strong&gt; - HTML, XML, JSON, and JetBrains internal format&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Merge support&lt;/strong&gt; for combining coverage from multiple test runs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CI integration
&lt;/h3&gt;

&lt;p&gt;The dotCover command-line tool runs in any CI environment. JetBrains TeamCity has built-in dotCover integration. Reports can be exported in formats compatible with Codecov, Coveralls, and SonarQube.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CLI tool&lt;/strong&gt; - free (included with &lt;code&gt;dotnet-dotcover&lt;/code&gt; global tool)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IDE plugin for Rider&lt;/strong&gt; - included with JetBrains Rider ($15.90/month first year)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visual Studio plugin&lt;/strong&gt; - included with dotUltimate ($28.90/month first year)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TeamCity&lt;/strong&gt; - built-in support&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Best-in-class IDE integration for .NET developers&lt;/li&gt;
&lt;li&gt;Continuous testing feature dramatically speeds up the feedback loop&lt;/li&gt;
&lt;li&gt;Accurate coverage for modern .NET (including async/await and LINQ)&lt;/li&gt;
&lt;li&gt;Free CLI tool for CI pipelines&lt;/li&gt;
&lt;li&gt;Strong integration with JetBrains ecosystem (TeamCity, Rider)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;.NET only - not applicable outside the Microsoft ecosystem&lt;/li&gt;
&lt;li&gt;IDE features require a paid JetBrains subscription&lt;/li&gt;
&lt;li&gt;Less community adoption than OpenCover for open source .NET projects&lt;/li&gt;
&lt;li&gt;Report format ecosystem is smaller than JaCoCo or Istanbul&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  10. OpenCover - free .NET coverage
&lt;/h2&gt;

&lt;p&gt;OpenCover is a free, open source code coverage tool for .NET Framework applications. It has been a staple of the .NET open source ecosystem for years, though its development has slowed with the rise of .NET Core and dotCover.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it does
&lt;/h3&gt;

&lt;p&gt;OpenCover uses the .NET profiling API to instrument assemblies at runtime and collect coverage data. It wraps around your test runner process and produces detailed XML reports compatible with most coverage reporting services.&lt;/p&gt;

&lt;h3&gt;
  
  
  Language support
&lt;/h3&gt;

&lt;p&gt;C#, VB.NET, and F# on .NET Framework. .NET Core support is limited - for modern .NET projects, the built-in &lt;code&gt;coverlet&lt;/code&gt; tool or dotCover is generally a better choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Profiling API instrumentation&lt;/strong&gt; - no source code changes needed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Branch and sequence point coverage&lt;/strong&gt; metrics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filter by namespace, class, or method&lt;/strong&gt; - exclude test assemblies and generated code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;XML output&lt;/strong&gt; compatible with ReportGenerator, Codecov, Coveralls, and SonarQube&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Works with NUnit, xUnit, and MSTest&lt;/strong&gt; runners&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CI integration
&lt;/h3&gt;

&lt;p&gt;OpenCover runs as a command-line wrapper around your test runner. Pair it with ReportGenerator for HTML reports and upload the XML output to your coverage service. Common in AppVeyor, Azure DevOps, and Jenkins pipelines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Completely free and open source under the MIT license.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Free and open source with no restrictions&lt;/li&gt;
&lt;li&gt;Accurate coverage data for .NET Framework projects&lt;/li&gt;
&lt;li&gt;Well-supported by downstream reporting tools&lt;/li&gt;
&lt;li&gt;Mature and battle-tested over many years&lt;/li&gt;
&lt;li&gt;ReportGenerator integration produces excellent HTML reports&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Limited .NET Core / .NET 6+ support - coverlet is better for modern .NET&lt;/li&gt;
&lt;li&gt;Development has slowed significantly&lt;/li&gt;
&lt;li&gt;Windows-only (does not run on Linux or macOS)&lt;/li&gt;
&lt;li&gt;Command-line interface is not as user-friendly as dotCover&lt;/li&gt;
&lt;li&gt;No IDE integration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  11. Bullseye Testing Technology - best for embedded C/C++
&lt;/h2&gt;

&lt;p&gt;Bullseye BullseyeCoverage is a commercial coverage tool designed for C and C++ projects, particularly in embedded systems, safety-critical software, and environments where gcov is not practical.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it does
&lt;/h3&gt;

&lt;p&gt;Bullseye instruments C and C++ source code at the preprocessing stage to insert coverage probes. It measures function coverage and condition/decision coverage (a stricter metric than simple branch coverage that is required by safety standards like DO-178C and IEC 62304).&lt;/p&gt;

&lt;h3&gt;
  
  
  Language support
&lt;/h3&gt;

&lt;p&gt;C and C++ only. Supports GCC, Clang, MSVC, Green Hills, Wind River, IAR, and other embedded compilers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Condition/decision coverage&lt;/strong&gt; - required for safety-critical certifications (DO-178C, IEC 62304)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Function and condition coverage&lt;/strong&gt; metrics with detailed reporting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedded system support&lt;/strong&gt; - works with cross-compilers and target hardware&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low overhead instrumentation&lt;/strong&gt; suitable for resource-constrained environments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coverage browser&lt;/strong&gt; GUI for exploring results&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Merge support&lt;/strong&gt; for combining runs from different test configurations or hardware targets&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CI integration
&lt;/h3&gt;

&lt;p&gt;Bullseye runs from the command line and integrates with Make, CMake, and other build systems. Coverage data can be exported for integration with Jenkins and other CI platforms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Named user license&lt;/strong&gt; - from $800/seat&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Floating license&lt;/strong&gt; - from $1,600/seat&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Site license&lt;/strong&gt; - custom pricing&lt;/li&gt;
&lt;li&gt;Free evaluation available&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Condition/decision coverage meets safety certification requirements&lt;/li&gt;
&lt;li&gt;Works with embedded and cross-compilation toolchains&lt;/li&gt;
&lt;li&gt;Low runtime overhead suitable for testing on target hardware&lt;/li&gt;
&lt;li&gt;Long track record in safety-critical industries (aerospace, automotive, medical)&lt;/li&gt;
&lt;li&gt;Excellent support for complex C++ features&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Expensive compared to free alternatives like gcov&lt;/li&gt;
&lt;li&gt;C/C++ only&lt;/li&gt;
&lt;li&gt;Closed source with proprietary license&lt;/li&gt;
&lt;li&gt;No built-in CI dashboard or PR integration&lt;/li&gt;
&lt;li&gt;Learning curve for condition/decision coverage concepts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  12. gcov/lcov - best free option for C and C++
&lt;/h2&gt;

&lt;p&gt;gcov is the coverage tool built into GCC (GNU Compiler Collection), and lcov is a graphical front-end that generates HTML reports from gcov data. Together, they provide the most widely used free coverage solution for C and C++ projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it does
&lt;/h3&gt;

&lt;p&gt;gcov works by compiling your code with special GCC flags (&lt;code&gt;--coverage&lt;/code&gt; or &lt;code&gt;-fprofile-arcs -ftest-coverage&lt;/code&gt;) that insert instrumentation. When the program runs, it writes execution counts to &lt;code&gt;.gcda&lt;/code&gt; files. lcov collects these files and produces LCOV-format reports and HTML pages showing line-by-line coverage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Language support
&lt;/h3&gt;

&lt;p&gt;C, C++, Fortran, and other GCC-supported languages. Clang also supports gcov-compatible output through its &lt;code&gt;--coverage&lt;/code&gt; flag, so lcov works with both GCC and Clang toolchains.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Line and branch coverage&lt;/strong&gt; at the source level&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built into GCC&lt;/strong&gt; - no separate installation for the core tool&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;lcov HTML reports&lt;/strong&gt; with per-file and per-function breakdown&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LCOV format&lt;/strong&gt; is a universal standard ingested by Codecov, Coveralls, SonarQube, and others&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;genhtml&lt;/strong&gt; tool generates detailed, navigable HTML reports&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Differential coverage&lt;/strong&gt; with lcov's &lt;code&gt;--diff&lt;/code&gt; option&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CI integration
&lt;/h3&gt;

&lt;p&gt;Add &lt;code&gt;--coverage&lt;/code&gt; to your GCC/Clang flags, run tests, then use lcov to generate an LCOV report. Upload the &lt;code&gt;.info&lt;/code&gt; file to Codecov or Coveralls. Works in any CI environment. GitHub Actions, GitLab CI, and Jenkins all have well-documented gcov/lcov workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Completely free. gcov is part of GCC (GPL), and lcov is distributed under the GPL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Free and built into the most widely used C/C++ compiler&lt;/li&gt;
&lt;li&gt;LCOV format is universally supported by reporting tools&lt;/li&gt;
&lt;li&gt;Zero additional dependencies for basic coverage with GCC&lt;/li&gt;
&lt;li&gt;Works with both GCC and Clang toolchains&lt;/li&gt;
&lt;li&gt;lcov HTML reports are clean and easy to navigate&lt;/li&gt;
&lt;li&gt;Enormous community with extensive documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Requires recompilation with coverage flags - not always practical for large projects&lt;/li&gt;
&lt;li&gt;Branch coverage output can be verbose and hard to interpret&lt;/li&gt;
&lt;li&gt;gcov data files can accumulate and require cleanup between runs&lt;/li&gt;
&lt;li&gt;No condition/decision coverage (unlike Bullseye) for safety certifications&lt;/li&gt;
&lt;li&gt;No built-in dashboard or historical tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to choose the right coverage tool
&lt;/h2&gt;

&lt;p&gt;Choosing a coverage tool depends on three factors: your programming language, your team size, and what you need beyond raw coverage numbers.&lt;/p&gt;

&lt;h3&gt;
  
  
  By language
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript/TypeScript&lt;/strong&gt; - Istanbul/nyc is the only choice. It is built into Jest and works with every major JS test framework.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python&lt;/strong&gt; - Coverage.py via pytest-cov. There is no real alternative.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Java/Kotlin/Scala&lt;/strong&gt; - JaCoCo. It is the industry standard with excellent build tool integration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C#/.NET&lt;/strong&gt; - dotCover for IDE integration, coverlet for CI (modern .NET), or OpenCover for .NET Framework.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C/C++&lt;/strong&gt; - gcov/lcov for most projects. Bullseye for safety-critical or embedded work requiring condition/decision coverage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  By team needs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Solo developer or small team&lt;/strong&gt; - use a free instrumentation tool plus Codecov or Coveralls free tier for PR feedback.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mid-size team (10-50 developers)&lt;/strong&gt; - Codecov Team or Coveralls Pro for dedicated coverage reporting, or SonarQube Developer Edition if you also want code quality and security analysis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise or polyglot monorepo&lt;/strong&gt; - SonarQube Enterprise for unified quality management, or Codecov Enterprise for dedicated coverage with self-hosted option.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teams already using code quality platforms&lt;/strong&gt; - Codacy or DeepSource if you want coverage as part of a broader quality workflow without adding another tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Coverage metrics that matter
&lt;/h3&gt;

&lt;p&gt;Not all coverage metrics are equally useful. Here is what to focus on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Branch coverage&lt;/strong&gt; is more valuable than line coverage because it catches untested conditional paths&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coverage on new code&lt;/strong&gt; is more actionable than overall coverage - enforce standards on what is being added, not legacy code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coverage diff per PR&lt;/strong&gt; is the most practical metric for code review - it tells reviewers whether a change includes adequate tests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Function coverage&lt;/strong&gt; is a good sanity check but too coarse for serious quality enforcement&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting up coverage in CI - a practical workflow
&lt;/h2&gt;

&lt;p&gt;Regardless of which tools you choose, the workflow follows the same pattern:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Generate coverage data.&lt;/strong&gt; Configure your test runner to produce coverage output. For JavaScript, add &lt;code&gt;--coverage&lt;/code&gt; to Jest or wrap with nyc. For Python, use &lt;code&gt;pytest --cov&lt;/code&gt;. For Java, add the JaCoCo plugin to your build.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Export in a standard format.&lt;/strong&gt; Use LCOV, Cobertura XML, or JaCoCo XML. These formats are understood by every reporting tool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Upload to a reporting service.&lt;/strong&gt; Add a CI step to send the report to Codecov, Coveralls, or SonarQube. Most services provide one-line CI configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Configure quality gates.&lt;/strong&gt; Set a minimum coverage threshold on new code (80% is a common starting point). Configure the service to post PR status checks so sub-threshold PRs cannot be merged.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Review coverage in PRs.&lt;/strong&gt; Use the PR comment or status check to evaluate whether new code includes adequate tests before approving.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our recommendations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best overall coverage reporting platform:&lt;/strong&gt; Codecov. Its PR integration, flag system, and carryforward flags make it the most practical choice for teams that want actionable coverage feedback on every pull request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best free setup for open source:&lt;/strong&gt; Istanbul/JaCoCo/Coverage.py (depending on language) paired with Codecov's free open source tier. This combination provides professional-grade coverage tracking at zero cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for unified quality management:&lt;/strong&gt; SonarQube. If your team already uses SonarQube for code quality and security, adding coverage tracking to the same platform is the logical choice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for teams wanting minimal tool sprawl:&lt;/strong&gt; Codacy or DeepSource. Both platforms combine coverage with code quality, security scanning, and duplication detection, reducing the number of tools your team needs to manage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for safety-critical C/C++:&lt;/strong&gt; Bullseye. Its condition/decision coverage is the only way to meet DO-178C and IEC 62304 certification requirements without building custom tooling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Code test coverage is a means to an end, not an end in itself. The goal is not to achieve a specific percentage - it is to have confidence that your tests exercise the code paths that matter. A project with 70% coverage focused on business logic and edge cases is better tested than one with 95% coverage that mostly tests trivial getters and setters.&lt;/p&gt;

&lt;p&gt;The best coverage tools make coverage data visible and actionable at the point where it matters most: during code review. When a reviewer can see that a pull request adds 200 lines of code with 0% coverage, they can ask for tests before the code ships. That single workflow improvement prevents more bugs than any coverage threshold ever will.&lt;/p&gt;

&lt;p&gt;Choose a tool that fits your language and workflow, set a reasonable threshold on new code, and focus your testing effort on the code that carries the most risk. The tools in this guide give you everything you need to do that effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is a good code coverage percentage to aim for?
&lt;/h3&gt;

&lt;p&gt;Most teams target 80% line coverage as a practical baseline. Reaching 100% is rarely worth the effort because it forces you to write tests for trivial code paths like getters, setters, and unreachable error handlers. The more important metric is branch coverage, which measures whether both the true and false paths of every conditional have been tested. A project with 75% branch coverage and 80% line coverage is generally better tested than one with 95% line coverage but only 50% branch coverage. Focus on covering critical business logic and edge cases rather than chasing a specific number.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the difference between line coverage, branch coverage, and function coverage?
&lt;/h3&gt;

&lt;p&gt;Line coverage measures the percentage of executable lines that were run during tests. Branch coverage measures whether both outcomes of every decision point (if/else, switch cases, ternary operators) were exercised. Function coverage measures the percentage of functions or methods that were called at least once. Branch coverage is the most meaningful metric because a line can be covered without testing all its conditional paths. For example, an if statement on a single line might show 100% line coverage even if only the true branch was tested. Most coverage tools report all three metrics, and mature teams prioritize branch coverage alongside line coverage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Are free code coverage tools good enough for production projects?
&lt;/h3&gt;

&lt;p&gt;Yes. Istanbul/nyc, Coverage.py, JaCoCo, gcov/lcov, and OpenCover are all free and open source tools used by thousands of production projects including major open source frameworks. These tools generate accurate coverage data locally and in CI pipelines. What free tools lack compared to paid platforms like Codecov and Coveralls is centralized reporting - historical trends, PR comments with coverage diffs, badge generation, and team-level dashboards. Many teams pair a free instrumentation tool with a free-tier reporting service like Codecov (free for open source) or Coveralls (free for public repos) to get both accurate data and good reporting.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I integrate code coverage into my CI/CD pipeline?
&lt;/h3&gt;

&lt;p&gt;The general pattern is three steps. First, configure your test runner to generate a coverage report in a standard format like LCOV, Cobertura XML, or JaCoCo XML. Second, add a step in your CI workflow (GitHub Actions, GitLab CI, Jenkins, etc.) to upload that report to a coverage service like Codecov, Coveralls, or SonarQube. Third, configure the service to post coverage results as a PR comment or status check so reviewers see coverage impact before merging. Most coverage services provide one-line CI configuration snippets. For example, Codecov requires only adding their GitHub Action and it auto-detects common report formats.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use multiple coverage tools together?
&lt;/h3&gt;

&lt;p&gt;Yes, and many teams do. A typical setup uses a language-specific instrumentation tool (like Istanbul for JavaScript or JaCoCo for Java) to generate raw coverage data, then uploads that data to a reporting platform (like Codecov or SonarQube) for visualization and PR integration. In polyglot projects, you might use Istanbul for your frontend, JaCoCo for your backend, and Coverage.py for your data pipeline - then aggregate all reports in Codecov or SonarQube for a unified view. The key is standardizing on a common report format like LCOV or Cobertura XML that all your reporting tools can ingest.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does high code coverage guarantee bug-free software?
&lt;/h3&gt;

&lt;p&gt;No. Code coverage measures whether lines or branches were executed during tests, not whether the tests actually verify correct behavior. A test that calls a function without any assertions will increase coverage without catching any bugs. This is sometimes called 'coverage theater.' Mutation testing tools like Stryker, PIT, and mutmut address this gap by modifying your source code and checking whether your tests detect the changes. High coverage is a necessary but not sufficient condition for well-tested software. The quality of your assertions matters more than the coverage percentage.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://aicodereview.cc/blog/best-code-test-coverage-tools/" rel="noopener noreferrer"&gt;aicodereview.cc&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>ai</category>
      <category>programming</category>
      <category>tools</category>
    </item>
    <item>
      <title>12 Best Code Smell Detection Tools in 2026 - Complete Guide</title>
      <dc:creator>Rahul Singh</dc:creator>
      <pubDate>Fri, 10 Apr 2026 22:00:00 +0000</pubDate>
      <link>https://dev.to/rahulxsingh/12-best-code-smell-detection-tools-in-2026-complete-guide-c76</link>
      <guid>https://dev.to/rahulxsingh/12-best-code-smell-detection-tools-in-2026-complete-guide-c76</guid>
      <description>&lt;h2&gt;
  
  
  What are code smells?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Code smells are surface-level indicators of deeper design problems in your codebase.&lt;/strong&gt; The term was popularized by Martin Fowler and Kent Beck in the book &lt;em&gt;Refactoring: Improving the Design of Existing Code&lt;/em&gt;. A code smell does not mean the code is broken - it compiles, it passes tests, it works - but it signals that something in the structure will cause problems as the project grows.&lt;/p&gt;

&lt;p&gt;Think of code smells like warning signs on a road. A sharp curve sign does not mean an accident has happened, but it tells you to slow down and pay attention. Similarly, a 500-line method does not mean there is a bug, but it strongly suggests the code will be difficult to test, debug, and modify in the future.&lt;/p&gt;

&lt;p&gt;The cost of ignoring code smells compounds over time. A study by the Technical University of Munich found that classes with detected code smells are &lt;strong&gt;3.4 times more likely to contain defects&lt;/strong&gt; than clean classes. Another study from Microsoft Research showed that files with high code smell density require &lt;strong&gt;2.5 times more effort&lt;/strong&gt; to modify during subsequent development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common types of code smells
&lt;/h2&gt;

&lt;p&gt;Before diving into tools, understanding the major categories of code smells helps you evaluate which tools offer the most relevant coverage for your codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bloaters
&lt;/h3&gt;

&lt;p&gt;Bloaters are code smells where something has grown too large to manage effectively.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Long Method&lt;/strong&gt; - A method that does too much and should be split into smaller, focused methods. Generally, methods over 20-30 lines deserve scrutiny.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Large Class (God Class)&lt;/strong&gt; - A class that has accumulated too many responsibilities. It knows too much, does too much, and changes for too many reasons.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long Parameter List&lt;/strong&gt; - Methods that accept more than 3-4 parameters, making them hard to call correctly and signaling that the method may need restructuring.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Clumps&lt;/strong&gt; - Groups of variables that frequently appear together (like street, city, state, zip) and should be extracted into their own class or structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Primitive Obsession&lt;/strong&gt; - Using primitive types for domain concepts instead of creating small value objects (using a string for email instead of an Email type).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Object-orientation abusers
&lt;/h3&gt;

&lt;p&gt;These smells indicate misuse of object-oriented principles.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Feature Envy&lt;/strong&gt; - A method that uses data from another class more than its own, suggesting it belongs in that other class.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inappropriate Intimacy&lt;/strong&gt; - Two classes that depend too heavily on each other's internal details.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refused Bequest&lt;/strong&gt; - A subclass that inherits methods and data it does not need, indicating the inheritance hierarchy is wrong.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Switch Statements&lt;/strong&gt; - Complex switch/case blocks that should be replaced with polymorphism.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Change preventers
&lt;/h3&gt;

&lt;p&gt;These smells make future changes disproportionately difficult.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Divergent Change&lt;/strong&gt; - A class that gets modified for many different reasons, violating the Single Responsibility Principle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shotgun Surgery&lt;/strong&gt; - A single change that requires edits across many classes, indicating responsibilities are scattered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallel Inheritance Hierarchies&lt;/strong&gt; - Adding a subclass in one hierarchy forces you to add a subclass in another.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dispensables
&lt;/h3&gt;

&lt;p&gt;These are code elements that serve no useful purpose and should be removed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dead Code&lt;/strong&gt; - Unreachable or unused code that clutters the codebase.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplicated Code&lt;/strong&gt; - The same logic repeated in multiple places instead of being extracted into a shared method or class.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lazy Class&lt;/strong&gt; - A class that does too little to justify its existence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speculative Generality&lt;/strong&gt; - Abstractions added "just in case" that are never actually used.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Couplers
&lt;/h3&gt;

&lt;p&gt;These smells indicate excessive coupling between components.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Middle Man&lt;/strong&gt; - A class that delegates almost all its work to another class, adding no value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message Chains&lt;/strong&gt; - Long chains of method calls like &lt;code&gt;a.getB().getC().getD()&lt;/code&gt; that create tight coupling to the object graph structure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  12 best code smell detection tools compared
&lt;/h2&gt;

&lt;p&gt;Here is a quick comparison of the tools covered in this guide before we dive into detailed reviews.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Languages&lt;/th&gt;
&lt;th&gt;Smell Types&lt;/th&gt;
&lt;th&gt;Pricing&lt;/th&gt;
&lt;th&gt;CI/CD Integration&lt;/th&gt;
&lt;th&gt;Auto-Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SonarQube&lt;/td&gt;
&lt;td&gt;30+&lt;/td&gt;
&lt;td&gt;5,000+ rules&lt;/td&gt;
&lt;td&gt;Free CE / $150+&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CodeClimate&lt;/td&gt;
&lt;td&gt;16+&lt;/td&gt;
&lt;td&gt;Maintainability&lt;/td&gt;
&lt;td&gt;Free OSS / $15/user&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Codacy&lt;/td&gt;
&lt;td&gt;49+&lt;/td&gt;
&lt;td&gt;Code patterns&lt;/td&gt;
&lt;td&gt;Free / $15/user&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSource&lt;/td&gt;
&lt;td&gt;11+&lt;/td&gt;
&lt;td&gt;800+ analyzers&lt;/td&gt;
&lt;td&gt;Free OSS / $12/user&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PMD&lt;/td&gt;
&lt;td&gt;Java, Apex, PLSQL, XML&lt;/td&gt;
&lt;td&gt;Design, coupling, size&lt;/td&gt;
&lt;td&gt;Free (OSS)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESLint&lt;/td&gt;
&lt;td&gt;JavaScript, TypeScript&lt;/td&gt;
&lt;td&gt;Complexity, structure&lt;/td&gt;
&lt;td&gt;Free (OSS)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pylint&lt;/td&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;Design, refactor&lt;/td&gt;
&lt;td&gt;Free (OSS)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IntelliJ IDEA&lt;/td&gt;
&lt;td&gt;20+&lt;/td&gt;
&lt;td&gt;6,000+ inspections&lt;/td&gt;
&lt;td&gt;Free CE / $249/yr&lt;/td&gt;
&lt;td&gt;IDE only&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NDepend&lt;/td&gt;
&lt;td&gt;.NET (C#, VB.NET)&lt;/td&gt;
&lt;td&gt;150+ rules&lt;/td&gt;
&lt;td&gt;$459/dev/yr&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JDeodorant&lt;/td&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;5 smell types&lt;/td&gt;
&lt;td&gt;Free (OSS)&lt;/td&gt;
&lt;td&gt;Eclipse only&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Designite&lt;/td&gt;
&lt;td&gt;Java, C#&lt;/td&gt;
&lt;td&gt;20+ design smells&lt;/td&gt;
&lt;td&gt;Free / $99/yr&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CodeAnt AI&lt;/td&gt;
&lt;td&gt;30+&lt;/td&gt;
&lt;td&gt;AI-powered&lt;/td&gt;
&lt;td&gt;Free / $19/user&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  1. SonarQube
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for: Teams that want the most comprehensive rule coverage across multiple languages.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/sonarqube"&gt;SonarQube&lt;/a&gt; is the industry standard for static code analysis and code smell detection. Its "Code Smells" category is a first-class concept in the platform, with thousands of rules specifically designed to identify maintainability issues across 30+ programming languages.&lt;/p&gt;

&lt;h3&gt;
  
  
  What smells it detects
&lt;/h3&gt;

&lt;p&gt;SonarQube groups issues into three categories: Bugs, Vulnerabilities, and Code Smells. The code smell rules cover cognitive complexity, duplicated code, long methods, deeply nested conditionals, unused variables, and many language-specific anti-patterns. Java alone has 600+ code smell rules. Python, JavaScript, TypeScript, C#, and C++ each have 200-400 rules.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Cognitive Complexity&lt;/strong&gt; metric is one of SonarQube's standout features. Unlike cyclomatic complexity, cognitive complexity weights control flow structures based on how difficult they are for humans to understand. This makes it much better at identifying methods that are genuinely hard to read versus methods that simply have many branches.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Community Edition&lt;/strong&gt; - Free and open source. Supports 30+ languages, code smells, bugs, and vulnerabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer Edition&lt;/strong&gt; - Starts at $150/year. Adds branch analysis, PR decoration, and additional languages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise Edition&lt;/strong&gt; - Starts at $20,000/year. Portfolio management, security reports, and regulatory compliance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Deepest code smell rule coverage in the market&lt;/li&gt;
&lt;li&gt;Quality Gates enforce smell thresholds on every PR&lt;/li&gt;
&lt;li&gt;Technical debt estimation shows the time cost of each smell&lt;/li&gt;
&lt;li&gt;Excellent Java, C#, and JavaScript/TypeScript support&lt;/li&gt;
&lt;li&gt;Self-hosted option keeps code on your infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Self-hosted setup requires a database and server maintenance&lt;/li&gt;
&lt;li&gt;Community Edition lacks PR decoration and branch analysis&lt;/li&gt;
&lt;li&gt;Can be noisy on legacy codebases without careful configuration&lt;/li&gt;
&lt;li&gt;Enterprise pricing is steep for small teams&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. CodeClimate
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for: Teams that prioritize maintainability tracking with minimal setup.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;CodeClimate Quality takes a different approach from rule-heavy tools. It focuses on a single &lt;strong&gt;Maintainability&lt;/strong&gt; rating (A through F) derived from structural analysis of your code. Rather than flagging hundreds of individual issues, it identifies patterns that reduce maintainability - duplication, complexity, and file length.&lt;/p&gt;

&lt;h3&gt;
  
  
  What smells it detects
&lt;/h3&gt;

&lt;p&gt;CodeClimate analyzes code for duplication, cognitive complexity, method length, file length, argument count, and return statements. It also integrates with language-specific linters (ESLint, RuboCop, Pylint) to pull in additional smell detection. The key metric is its maintainability GPA, which gives teams a single number to track over time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free&lt;/strong&gt; for open source projects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality&lt;/strong&gt; - $15/user/month for private repositories&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Clean, easy-to-understand maintainability scores&lt;/li&gt;
&lt;li&gt;Quick setup with GitHub, GitLab, and Bitbucket&lt;/li&gt;
&lt;li&gt;Duplication detection across entire codebase&lt;/li&gt;
&lt;li&gt;Trend tracking shows whether code health is improving or declining&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Fewer granular smell rules than SonarQube&lt;/li&gt;
&lt;li&gt;No auto-fix capability&lt;/li&gt;
&lt;li&gt;Limited to structural smells (does not detect design-level smells like feature envy)&lt;/li&gt;
&lt;li&gt;Less useful for languages outside the JavaScript/Ruby/Python ecosystem&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Codacy
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for: Polyglot teams that need broad language coverage with code smell detection built into PR workflows.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/codacy"&gt;Codacy&lt;/a&gt; supports 49+ languages and wraps dozens of open source analyzers (PMD, ESLint, Pylint, Checkstyle, and more) into a unified platform with consistent reporting and PR integration.&lt;/p&gt;

&lt;h3&gt;
  
  
  What smells it detects
&lt;/h3&gt;

&lt;p&gt;Codacy detects code patterns, complexity, duplication, and unused code across its supported languages. It categorizes issues by severity and type, with code smell categories including style, error-prone patterns, complexity, and performance. Each language uses purpose-built analyzers - PMD for Java, Pylint for Python, ESLint for JavaScript - giving you specialized detection without configuring each tool separately.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free&lt;/strong&gt; for open source and up to 5 users on private repos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pro&lt;/strong&gt; - $15/user/month with advanced security scanning and team management&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Business&lt;/strong&gt; - Custom pricing for enterprise features&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;49+ language support is the broadest in the market&lt;/li&gt;
&lt;li&gt;Bundles best-in-class open source analyzers&lt;/li&gt;
&lt;li&gt;PR comments with inline code smell annotations&lt;/li&gt;
&lt;li&gt;Free tier is genuinely usable for small teams&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Analysis can be slow on large repositories&lt;/li&gt;
&lt;li&gt;Aggregating multiple analyzers sometimes produces duplicate findings&lt;/li&gt;
&lt;li&gt;Custom rule creation is limited compared to SonarQube&lt;/li&gt;
&lt;li&gt;Some language analyzers are more mature than others&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. DeepSource
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for: Teams that want automated code smell detection with one-click fixes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/deepsource"&gt;DeepSource&lt;/a&gt; stands out for its Autofix feature, which can automatically generate pull requests to resolve detected code smells. It supports Python, Go, Java, JavaScript, TypeScript, Ruby, Rust, Kotlin, Scala, Swift, and C#.&lt;/p&gt;

&lt;h3&gt;
  
  
  What smells it detects
&lt;/h3&gt;

&lt;p&gt;DeepSource covers anti-patterns, bug risks, style issues, performance problems, and security vulnerabilities. For code smells specifically, it detects long functions, complex conditionals, dead code, unused imports, duplicated logic, and type-specific anti-patterns. Its analyzers are built in-house rather than wrapping third-party tools, which gives it more control over false positive rates.&lt;/p&gt;

&lt;p&gt;DeepSource claims a &lt;strong&gt;sub-5% false positive rate&lt;/strong&gt;, which is notably lower than most competitors. In practice, this means less time dismissing irrelevant findings and more time fixing real issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free&lt;/strong&gt; for open source projects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Business&lt;/strong&gt; - $12/user/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise&lt;/strong&gt; - Custom pricing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Autofix generates ready-to-merge PRs for many smells&lt;/li&gt;
&lt;li&gt;Low false positive rate reduces alert fatigue&lt;/li&gt;
&lt;li&gt;Clean dashboard with clear issue categorization&lt;/li&gt;
&lt;li&gt;TOML-based configuration is simple and version-controllable&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Supports 11 languages (fewer than Codacy or SonarQube)&lt;/li&gt;
&lt;li&gt;No self-hosted option for the cloud platform&lt;/li&gt;
&lt;li&gt;Design-level smells like feature envy and inappropriate intimacy are not covered&lt;/li&gt;
&lt;li&gt;Autofix works best for Python and Go, less reliable for other languages&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. PMD
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for: Java teams that want a free, mature, and highly configurable code smell analyzer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PMD is one of the oldest static analysis tools for Java, with deep rules for detecting design problems, code smells, and anti-patterns. It also supports Apex, PLSQL, Visualforce, and XML.&lt;/p&gt;

&lt;h3&gt;
  
  
  What smells it detects
&lt;/h3&gt;

&lt;p&gt;PMD's rule categories include Design, Code Style, Best Practices, Error Prone, Multithreading, and Performance. The Design rules are where code smell detection shines - they cover god classes, data classes, excessive class length, excessive method length, cyclomatic complexity, coupling between objects, depth of inheritance, and law of Demeter violations.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Copy-Paste Detector (CPD)&lt;/strong&gt; included with PMD is one of the best duplication detection tools available. It works across Java, C, C++, JavaScript, Python, Go, and several other languages, even though PMD's core analysis is Java-focused.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free&lt;/strong&gt; and open source (BSD license)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Mature and battle-tested with 20+ years of development&lt;/li&gt;
&lt;li&gt;Highly configurable with XML rulesets&lt;/li&gt;
&lt;li&gt;CPD duplication detection is best in class&lt;/li&gt;
&lt;li&gt;Integrates with Maven, Gradle, Ant, and all major CI systems&lt;/li&gt;
&lt;li&gt;Massive community with extensive documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Java-centric (limited value for non-Java teams)&lt;/li&gt;
&lt;li&gt;XML configuration can be verbose&lt;/li&gt;
&lt;li&gt;No built-in dashboard or trend tracking&lt;/li&gt;
&lt;li&gt;No auto-fix capabilities&lt;/li&gt;
&lt;li&gt;Requires manual integration with PR workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. ESLint
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for: JavaScript and TypeScript teams that want extensible smell detection integrated into their existing workflow.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ESLint is the standard linter for JavaScript and TypeScript. While it is primarily known for style enforcement, its complexity and best-practice rules provide meaningful code smell detection for frontend and Node.js projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  What smells it detects
&lt;/h3&gt;

&lt;p&gt;ESLint's built-in rules cover cyclomatic complexity (&lt;code&gt;complexity&lt;/code&gt;), maximum depth (&lt;code&gt;max-depth&lt;/code&gt;), maximum lines per function (&lt;code&gt;max-lines-per-function&lt;/code&gt;), maximum parameters (&lt;code&gt;max-params&lt;/code&gt;), and maximum statements (&lt;code&gt;max-statements&lt;/code&gt;). The &lt;code&gt;no-unused-vars&lt;/code&gt;, &lt;code&gt;no-shadow&lt;/code&gt;, and &lt;code&gt;no-redeclare&lt;/code&gt; rules catch dispensable code smells.&lt;/p&gt;

&lt;p&gt;The real power comes from plugins. &lt;code&gt;eslint-plugin-sonarjs&lt;/code&gt; adds SonarQube's cognitive complexity and code smell rules to ESLint. &lt;code&gt;eslint-plugin-jsdoc&lt;/code&gt; catches documentation smells. Custom rules can be written to detect project-specific anti-patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free&lt;/strong&gt; and open source (MIT license)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Already installed in most JavaScript/TypeScript projects&lt;/li&gt;
&lt;li&gt;Highly extensible through plugins&lt;/li&gt;
&lt;li&gt;Auto-fix for many rules via &lt;code&gt;--fix&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Integrates with every editor and CI system&lt;/li&gt;
&lt;li&gt;Flat config system (eslint.config.js) is clean and composable&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Limited to JavaScript and TypeScript&lt;/li&gt;
&lt;li&gt;Complexity rules require manual threshold configuration&lt;/li&gt;
&lt;li&gt;Does not detect OOP smells (feature envy, god class) since JS is not class-heavy&lt;/li&gt;
&lt;li&gt;Plugin quality varies significantly&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. Pylint
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for: Python teams that want thorough code analysis including structural smell detection.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pylint is the most comprehensive Python linter, with rule categories that go well beyond syntax checking into genuine code smell territory. Its Design and Refactor categories specifically target structural issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  What smells it detects
&lt;/h3&gt;

&lt;p&gt;Pylint's Refactor category includes rules for too-many-arguments, too-many-branches, too-many-instance-attributes, too-many-locals, too-many-return-statements, too-many-statements, too-few-public-methods, and duplicate-code. The Design category covers issues like too-many-ancestors (deep inheritance) and too-many-public-methods (god class indicator).&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;similarity checker&lt;/strong&gt; (&lt;code&gt;--disable=all --enable=similarities&lt;/code&gt;) can scan entire projects for duplicated code blocks, similar to PMD's CPD but for Python.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free&lt;/strong&gt; and open source (GPL-2.0)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Most thorough Python analysis available&lt;/li&gt;
&lt;li&gt;Configurable thresholds for all complexity metrics&lt;/li&gt;
&lt;li&gt;Code rating score (0-10) provides a quick health metric&lt;/li&gt;
&lt;li&gt;Active development with regular updates&lt;/li&gt;
&lt;li&gt;Integrates with all Python editors and CI systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Can be very noisy with default settings&lt;/li&gt;
&lt;li&gt;Python-only&lt;/li&gt;
&lt;li&gt;No auto-fix for structural smells&lt;/li&gt;
&lt;li&gt;Configuration requires a &lt;code&gt;.pylintrc&lt;/code&gt; file or &lt;code&gt;pyproject.toml&lt;/code&gt; section&lt;/li&gt;
&lt;li&gt;Slower than alternatives like Ruff for pure linting&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. IntelliJ IDEA inspections
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for: Individual developers and small teams who want real-time code smell detection while writing code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;JetBrains IntelliJ IDEA (and its family of IDEs - PyCharm, WebStorm, Rider) includes over 6,000 code inspections that run in real-time as you type. Many of these inspections detect code smells and offer one-click refactoring to fix them.&lt;/p&gt;

&lt;h3&gt;
  
  
  What smells it detects
&lt;/h3&gt;

&lt;p&gt;IntelliJ's inspections cover method complexity, class size, parameter count, duplicated code fragments, unused declarations, overly complex expressions, and dozens of language-specific anti-patterns. The "Structural Search and Replace" feature lets you define custom smell patterns using a template language.&lt;/p&gt;

&lt;p&gt;The IDE's refactoring tools are tightly integrated with smell detection. When IDEA flags a long method, it offers "Extract Method" right in the context menu. When it detects duplicated code, it offers "Extract to method/variable" to eliminate the duplication.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Community Edition&lt;/strong&gt; - Free for Java, Kotlin, Groovy, and Scala&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ultimate Edition&lt;/strong&gt; - $249/year first year for individuals, $599/year for organizations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Real-time detection as you type (no CI pipeline needed)&lt;/li&gt;
&lt;li&gt;One-click refactoring for detected smells&lt;/li&gt;
&lt;li&gt;6,000+ inspections across 20+ languages&lt;/li&gt;
&lt;li&gt;Custom inspections via Structural Search&lt;/li&gt;
&lt;li&gt;Deepest IDE-based analysis available&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;IDE-only (does not run in CI/CD without Qodana)&lt;/li&gt;
&lt;li&gt;Requires every developer to use JetBrains IDEs&lt;/li&gt;
&lt;li&gt;Results are not shared across the team without Qodana&lt;/li&gt;
&lt;li&gt;Inspection profiles need team-wide standardization&lt;/li&gt;
&lt;li&gt;Ultimate Edition is expensive at scale&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  9. NDepend
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for: .NET teams that need deep architectural analysis and code smell metrics.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;NDepend is the most specialized code quality tool for the .NET ecosystem. It analyzes C# and VB.NET codebases with over 150 code rules, many of which target code smells and design issues specific to .NET patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  What smells it detects
&lt;/h3&gt;

&lt;p&gt;NDepend excels at detecting architectural and design-level smells. Its rules cover class coupling, method complexity, type cohesion (LCOM - Lack of Cohesion of Methods), depth of inheritance, afferent and efferent coupling, cyclomatic complexity, and IL complexity. The &lt;strong&gt;CQLinq&lt;/strong&gt; query language lets you write custom code smell rules using LINQ-style queries over your codebase's structure.&lt;/p&gt;

&lt;p&gt;NDepend's dependency graph and matrix visualizations make it easy to spot inappropriate intimacy and circular dependencies at the namespace and assembly level.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Professional&lt;/strong&gt; - $459/developer/year&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise&lt;/strong&gt; - $919/developer/year (includes build server license)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Deepest .NET analysis available&lt;/li&gt;
&lt;li&gt;CQLinq enables powerful custom queries&lt;/li&gt;
&lt;li&gt;Dependency visualization for architectural smells&lt;/li&gt;
&lt;li&gt;Trend tracking across builds&lt;/li&gt;
&lt;li&gt;Integrates with Visual Studio and Azure DevOps&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;.NET only&lt;/li&gt;
&lt;li&gt;Expensive compared to cross-platform alternatives&lt;/li&gt;
&lt;li&gt;Steep learning curve for CQLinq&lt;/li&gt;
&lt;li&gt;No free tier (14-day trial only)&lt;/li&gt;
&lt;li&gt;Overkill for small projects&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  10. JDeodorant
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for: Java developers who want automated refactoring suggestions for specific code smells.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;JDeodorant is an Eclipse plugin developed by researchers at Concordia University. It is specifically designed to detect five types of code smells and suggest concrete refactoring opportunities to fix them.&lt;/p&gt;

&lt;h3&gt;
  
  
  What smells it detects
&lt;/h3&gt;

&lt;p&gt;JDeodorant focuses on five smells with academic rigor:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Feature Envy&lt;/strong&gt; - Detects methods that use another class's data more than their own and suggests Move Method refactoring&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type Checking&lt;/strong&gt; - Identifies switch/if-else chains that should be replaced with polymorphism and suggests Replace Conditional with Polymorphism&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long Method&lt;/strong&gt; - Finds opportunities to extract smaller methods and suggests Extract Method refactoring&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;God Class&lt;/strong&gt; - Detects classes with too many responsibilities and suggests Extract Class refactoring&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplicated Code&lt;/strong&gt; - Identifies code clones and suggests extraction&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free&lt;/strong&gt; and open source&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Purpose-built for code smell detection (not a general linter)&lt;/li&gt;
&lt;li&gt;Suggests specific refactoring operations, not just warnings&lt;/li&gt;
&lt;li&gt;Backed by academic research on smell detection accuracy&lt;/li&gt;
&lt;li&gt;Completely free&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Eclipse-only (no VS Code, IntelliJ, or CLI support)&lt;/li&gt;
&lt;li&gt;Limited to Java&lt;/li&gt;
&lt;li&gt;Only 5 smell types (no complexity metrics or coupling analysis)&lt;/li&gt;
&lt;li&gt;Development has slowed in recent years&lt;/li&gt;
&lt;li&gt;No CI/CD integration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  11. Designite
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for: Researchers and teams that want to quantify design smells and track architectural degradation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Designite is a code smell detection tool with a focus on design-level and architectural smells. Available in Java and C# editions, it categorizes smells into implementation smells, design smells, and architecture smells - a more granular taxonomy than most tools provide.&lt;/p&gt;

&lt;h3&gt;
  
  
  What smells it detects
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Implementation Smells&lt;/strong&gt; - Long method, complex method, long parameter list, long statement, missing default case, empty catch clause.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design Smells&lt;/strong&gt; - Broken modularization, cyclic-dependent modularization, god class, feature envy, insufficient modularization, hub-like modularization, unnecessary abstraction, deep hierarchy, multipath hierarchy, wide hierarchy, rebellious hierarchy, unfactored hierarchy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Architecture Smells&lt;/strong&gt; - Cyclic dependency, unstable dependency, ambiguous interface, god component, feature concentration, scattered functionality, dense structure.&lt;/p&gt;

&lt;p&gt;This three-tier classification makes Designite unique among tools - it catches problems at the method, class, and component level.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DesigniteJava&lt;/strong&gt; - Free and open source&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Designite for C#&lt;/strong&gt; - $99/year per user&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Three-tier smell taxonomy (implementation, design, architecture)&lt;/li&gt;
&lt;li&gt;Detects architectural smells that other tools miss&lt;/li&gt;
&lt;li&gt;Export to CSV for custom analysis&lt;/li&gt;
&lt;li&gt;DesigniteJava is completely free&lt;/li&gt;
&lt;li&gt;Academic backing with published research&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Limited to Java and C#&lt;/li&gt;
&lt;li&gt;No PR integration or inline comments&lt;/li&gt;
&lt;li&gt;Basic UI compared to commercial tools&lt;/li&gt;
&lt;li&gt;No auto-fix capability&lt;/li&gt;
&lt;li&gt;Small community compared to SonarQube or ESLint&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  12. CodeAnt AI
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for: Teams that want AI-powered code smell detection with auto-fix across multiple languages.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/codeant-ai"&gt;CodeAnt AI&lt;/a&gt; uses AI models to detect code quality issues including code smells, security vulnerabilities, and performance problems. It positions itself as a modern alternative to traditional rule-based tools by using machine learning to understand code patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  What smells it detects
&lt;/h3&gt;

&lt;p&gt;CodeAnt AI covers duplicated code, dead code, complex functions, large classes, long parameter lists, deeply nested conditionals, and code style inconsistencies. Its AI approach means it can detect smells that do not match predefined patterns - for example, it may flag a method as doing too many things based on semantic analysis rather than a line count threshold.&lt;/p&gt;

&lt;p&gt;The tool provides auto-fix suggestions powered by AI, which can generate refactored code for detected smells. It supports 30+ languages and integrates with GitHub, GitLab, and Bitbucket.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free&lt;/strong&gt; for open source and small teams&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pro&lt;/strong&gt; - $19/user/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise&lt;/strong&gt; - Custom pricing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;AI-powered detection catches non-obvious smells&lt;/li&gt;
&lt;li&gt;Auto-fix generates refactored code&lt;/li&gt;
&lt;li&gt;30+ language support&lt;/li&gt;
&lt;li&gt;Quick setup with GitHub/GitLab/Bitbucket integration&lt;/li&gt;
&lt;li&gt;PR-level analysis with inline comments&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;AI suggestions can occasionally be inaccurate&lt;/li&gt;
&lt;li&gt;Newer tool with a smaller track record than SonarQube or PMD&lt;/li&gt;
&lt;li&gt;Black-box detection (harder to understand why something was flagged)&lt;/li&gt;
&lt;li&gt;Less configurable than rule-based tools&lt;/li&gt;
&lt;li&gt;Dependent on cloud infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to choose the right code smell detection tool
&lt;/h2&gt;

&lt;h3&gt;
  
  
  By team size
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Solo developers&lt;/strong&gt; - IntelliJ IDEA inspections or ESLint/Pylint give you real-time feedback without any infrastructure. JDeodorant is a good addition for Java developers in Eclipse.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Small teams (2-10)&lt;/strong&gt; - DeepSource or CodeAnt AI provide cloud-hosted analysis with free tiers. Codacy is another strong option with its generous free plan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Medium teams (10-50)&lt;/strong&gt; - SonarQube Developer Edition or Codacy Pro give you PR decoration, branch analysis, and team dashboards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Large teams (50+)&lt;/strong&gt; - SonarQube Enterprise or CodeClimate with Codacy Business for portfolio-level visibility and governance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  By language
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Java&lt;/strong&gt; - SonarQube, PMD, JDeodorant, Designite, IntelliJ IDEA&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python&lt;/strong&gt; - Pylint, DeepSource, SonarQube, Codacy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript/TypeScript&lt;/strong&gt; - ESLint with sonarjs plugin, SonarQube, DeepSource, CodeClimate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;.NET (C#)&lt;/strong&gt; - NDepend, SonarQube, Designite, Rider inspections&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-language&lt;/strong&gt; - SonarQube, Codacy, CodeAnt AI, DeepSource&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  By budget
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;$0&lt;/strong&gt; - PMD + ESLint/Pylint for language-specific detection, SonarQube Community Edition for multi-language, DeepSource free tier for cloud-hosted&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$10-20/user/month&lt;/strong&gt; - DeepSource Business, Codacy Pro, CodeAnt AI Pro&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$150-500/year&lt;/strong&gt; - SonarQube Developer Edition, NDepend Professional&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$20,000+/year&lt;/strong&gt; - SonarQube Enterprise for large organizations with governance requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting up code smell detection in your CI pipeline
&lt;/h2&gt;

&lt;p&gt;The most impactful way to use code smell detection tools is to run them automatically on every pull request. Here is a practical approach that works for most teams.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Choose your tools
&lt;/h3&gt;

&lt;p&gt;Pick one comprehensive tool (SonarQube, Codacy, or DeepSource) for your CI pipeline and one language-specific tool (ESLint, Pylint, or PMD) for developer-local feedback. This gives you both fast local checks and thorough PR-level analysis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Set quality thresholds
&lt;/h3&gt;

&lt;p&gt;Do not enable every rule at once on an existing codebase. Start with high-confidence, high-impact rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cognitive complexity&lt;/strong&gt; above 15 for any single method&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplicated blocks&lt;/strong&gt; longer than 10 lines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Method length&lt;/strong&gt; above 50 lines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File length&lt;/strong&gt; above 500 lines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parameter count&lt;/strong&gt; above 5&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: Enforce on new code only
&lt;/h3&gt;

&lt;p&gt;Most tools support "new code" analysis that only flags issues introduced in the current PR. This prevents overwhelming developers with thousands of pre-existing issues while ensuring code quality improves with every merge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Track trends
&lt;/h3&gt;

&lt;p&gt;Use your tool's dashboard to monitor code smell trends over time. The goal is not zero smells (that is unrealistic for any real project) but a consistent downward trend. SonarQube's Quality Gate, CodeClimate's GPA, and DeepSource's health score all provide this at a glance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code smell detection best practices
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Start with the worst offenders.&lt;/strong&gt; Focus on god classes and long methods first. These two smell types account for the majority of maintainability problems and are the easiest for teams to agree on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tune thresholds to your codebase.&lt;/strong&gt; A method complexity threshold of 10 might work for a new project but generate hundreds of false positives on a legacy codebase. Start lenient and tighten over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Combine static and IDE-based tools.&lt;/strong&gt; Running ESLint in your editor catches smells as you type. Running SonarQube in CI catches smells that slip through. The two approaches complement each other.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do not treat all smells equally.&lt;/strong&gt; A god class in a core domain module is far more damaging than a long method in a test file. Prioritize smells in high-change, high-risk areas of the codebase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Review smell trends, not just counts.&lt;/strong&gt; A codebase with 500 code smells that is decreasing by 20 per sprint is healthier than one with 100 smells that is increasing by 10 per sprint. Direction matters more than absolute numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verdict
&lt;/h2&gt;

&lt;p&gt;For most teams, &lt;strong&gt;SonarQube Community Edition&lt;/strong&gt; combined with a language-specific linter (ESLint, Pylint, or PMD) provides the best code smell detection coverage at zero cost. If you want a cloud-hosted solution with auto-fix, &lt;strong&gt;DeepSource&lt;/strong&gt; offers the best balance of detection quality, low false positives, and automated remediation. For .NET teams, &lt;strong&gt;NDepend&lt;/strong&gt; is unmatched. And for teams that want AI-powered detection that goes beyond predefined rules, &lt;strong&gt;CodeAnt AI&lt;/strong&gt; is worth evaluating alongside the established options.&lt;/p&gt;

&lt;p&gt;The key is to start. Any code smell detection is better than none, and the tools have never been more accessible. Pick one, integrate it into your PR workflow, and your codebase will thank you within weeks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/blog/best-ai-code-review-tools"&gt;Best AI Code Review Tools in 2026&lt;/a&gt; - AI-powered tools that catch smells and bugs in pull requests&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/blog/sonarqube-review"&gt;SonarQube Review&lt;/a&gt; - In-depth look at SonarQube's features and setup&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/blog/deepsource-review"&gt;DeepSource Review&lt;/a&gt; - Detailed analysis of DeepSource's detection and Autofix&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/blog/best-code-quality-tools"&gt;Best Code Quality Tools&lt;/a&gt; - Broader comparison of code quality platforms&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/blog/code-review-best-practices"&gt;Code Review Best Practices&lt;/a&gt; - How to combine automated detection with human review&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What are code smells and why do they matter?
&lt;/h3&gt;

&lt;p&gt;Code smells are indicators of deeper structural problems in source code. They are not bugs - the code still works - but they signal maintainability issues that make the codebase harder to understand, modify, and extend over time. Common examples include long methods, god classes, feature envy, and duplicated code. Ignoring code smells leads to increasing technical debt, slower development velocity, and higher defect rates.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the best free code smell detection tool?
&lt;/h3&gt;

&lt;p&gt;For free code smell detection, SonarQube Community Edition is the most comprehensive option with support for 30+ languages. PMD and ESLint are excellent free alternatives for Java and JavaScript respectively. DeepSource offers a generous free tier for open source projects that includes code smell detection across Python, Go, Java, JavaScript, and Ruby.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can code smell detection tools automatically fix issues?
&lt;/h3&gt;

&lt;p&gt;Some tools offer automated fixes for certain code smells. DeepSource provides one-click Autofix for many issues. ESLint and Pylint can auto-fix formatting and simple structural issues with their --fix flags. IntelliJ IDEA offers built-in refactoring actions that can resolve smells like long methods and duplicated code. However, complex architectural smells like god classes or feature envy typically require manual refactoring guided by developer judgment.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do code smell detection tools differ from linters?
&lt;/h3&gt;

&lt;p&gt;Linters primarily check for syntax errors, formatting issues, and basic coding standards. Code smell detection tools go deeper by analyzing structural and design-level problems - things like class coupling, method complexity, inheritance depth, and responsibility distribution. A linter might flag an unused variable, while a code smell tool would flag an entire class that has grown too large and needs to be split into smaller, focused components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which code smell detection tool works best for Java projects?
&lt;/h3&gt;

&lt;p&gt;For Java projects, SonarQube provides the deepest code smell analysis with over 600 Java-specific rules. PMD is a strong free alternative with mature Java support. JDeodorant is purpose-built for detecting and refactoring Java code smells directly within Eclipse. IntelliJ IDEA's built-in inspections also offer excellent Java smell detection with one-click refactoring support.&lt;/p&gt;

&lt;h3&gt;
  
  
  How often should you run code smell detection?
&lt;/h3&gt;

&lt;p&gt;The most effective approach is to run code smell detection on every pull request as part of your CI/CD pipeline. This catches new smells before they enter the main branch. Additionally, run a full codebase scan weekly or monthly to track overall code health trends and prioritize technical debt reduction. Tools like SonarQube, Codacy, and DeepSource support both PR-level and scheduled full-scan workflows.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://aicodereview.cc/blog/best-code-smell-detection-tools/" rel="noopener noreferrer"&gt;aicodereview.cc&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>ai</category>
      <category>programming</category>
      <category>tools</category>
    </item>
    <item>
      <title>12 Best Code Audit Tools in 2026 - Quality and Security</title>
      <dc:creator>Rahul Singh</dc:creator>
      <pubDate>Fri, 10 Apr 2026 21:00:00 +0000</pubDate>
      <link>https://dev.to/rahulxsingh/12-best-code-audit-tools-in-2026-quality-and-security-eeb</link>
      <guid>https://dev.to/rahulxsingh/12-best-code-audit-tools-in-2026-quality-and-security-eeb</guid>
      <description>&lt;h2&gt;
  
  
  What is a code audit and why it matters
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A code audit is a systematic examination of source code to assess its quality, security posture, and compliance with standards.&lt;/strong&gt; Unlike daily code reviews that focus on individual pull requests, a code audit takes a holistic view of the entire codebase - identifying systemic vulnerabilities, accumulated technical debt, architectural weaknesses, and regulatory compliance gaps.&lt;/p&gt;

&lt;p&gt;Code audits matter because software rot is real. Every codebase accumulates technical debt over time as teams make pragmatic tradeoffs to hit deadlines. Without periodic audits, that debt compounds silently until it manifests as security breaches, production outages, or failed compliance certifications.&lt;/p&gt;

&lt;p&gt;The stakes are high. IBM's Cost of a Data Breach Report 2025 puts the average breach cost at $4.88 million. PCI-DSS 4.0 now mandates automated code analysis for custom application code. SOC 2 Type II auditors increasingly expect evidence of continuous security scanning. If your organization handles sensitive data, code audits are not optional - they are a business requirement.&lt;/p&gt;

&lt;p&gt;The good news is that modern code audit tools automate the most time-consuming parts of the process. They scan millions of lines of code in minutes, detect thousands of vulnerability patterns, and generate compliance-ready reports. The challenge is choosing the right tool for your specific needs - which is what this guide covers.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to perform a code audit
&lt;/h2&gt;

&lt;p&gt;Not every situation calls for the same type of audit. Here are the most common triggers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Annual compliance cycles&lt;/strong&gt; - SOC 2, PCI-DSS, HIPAA, and ISO 27001 all benefit from or require periodic code-level security assessments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pre-acquisition due diligence&lt;/strong&gt; - Buyers need to assess code quality, security risk, and technical debt before closing a deal&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Major architecture changes&lt;/strong&gt; - Migrating to microservices, changing frameworks, or adopting new languages warrants a baseline audit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Post-incident review&lt;/strong&gt; - After a security breach or major production outage, audit the codebase to find related vulnerabilities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New team onboarding&lt;/strong&gt; - When a new team inherits a codebase, an audit establishes the current state and priorities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pre-release security gates&lt;/strong&gt; - Critical releases should pass automated security audits before deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Internal vs external code audits
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Internal audits&lt;/strong&gt; are conducted by your own engineering or security team using automated tools and manual review. They are faster, cheaper, and can run continuously. The downside is potential blind spots - your team may have the same assumptions as the developers who wrote the code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;External audits&lt;/strong&gt; are performed by third-party security firms or consultants. They bring fresh eyes, specialized expertise, and credibility with auditors and regulators. The downsides are cost ($10,000-100,000+ per engagement) and limited frequency - most organizations can only afford one or two external audits per year.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The best approach combines both.&lt;/strong&gt; Run automated internal audits continuously using the tools in this guide, and supplement with annual external audits for high-risk systems. This gives you the breadth of automated scanning with the depth of expert human review.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to structure a code audit process
&lt;/h2&gt;

&lt;p&gt;A well-structured code audit follows these phases:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Define scope and objectives
&lt;/h3&gt;

&lt;p&gt;Decide what you are auditing and why. A compliance-focused audit prioritizes security vulnerabilities mapped to specific controls (OWASP Top 10, CWE Top 25). A quality-focused audit targets technical debt, code complexity, and maintainability. A pre-acquisition audit covers everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Run automated scans
&lt;/h3&gt;

&lt;p&gt;Use SAST tools to scan source code for vulnerabilities and quality issues. Run SCA tools to check dependencies for known CVEs. If you have running applications, add DAST scanning for runtime vulnerabilities. This phase generates the bulk of findings quickly.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Triage and prioritize findings
&lt;/h3&gt;

&lt;p&gt;Automated tools produce noise. Triage findings by severity, exploitability, and business impact. A critical SQL injection in a public-facing API matters more than a minor code style violation in an internal script. Use the tool's built-in severity ratings as a starting point, but apply your own business context.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Manual expert review
&lt;/h3&gt;

&lt;p&gt;Have experienced developers or security engineers review the automated findings, eliminate false positives, and investigate areas that automated tools miss - business logic flaws, architectural weaknesses, and authorization model correctness.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Report and remediate
&lt;/h3&gt;

&lt;p&gt;Document findings with clear severity ratings, reproduction steps, and remediation guidance. Prioritize fixes by risk. Track remediation progress and verify fixes through re-scanning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison table - best code audit tools at a glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Audit Focus&lt;/th&gt;
&lt;th&gt;Analysis Type&lt;/th&gt;
&lt;th&gt;Languages&lt;/th&gt;
&lt;th&gt;Free Tier&lt;/th&gt;
&lt;th&gt;Compliance&lt;/th&gt;
&lt;th&gt;Starting Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SonarQube&lt;/td&gt;
&lt;td&gt;Quality + Security&lt;/td&gt;
&lt;td&gt;SAST&lt;/td&gt;
&lt;td&gt;35+&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;SOC 2, PCI-DSS&lt;/td&gt;
&lt;td&gt;Free (Community)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Checkmarx&lt;/td&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;SAST, SCA, DAST&lt;/td&gt;
&lt;td&gt;25+&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;SOC 2, HIPAA, PCI-DSS&lt;/td&gt;
&lt;td&gt;~$40,000/year&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Veracode&lt;/td&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;SAST, SCA, DAST&lt;/td&gt;
&lt;td&gt;25+&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;SOC 2, HIPAA, PCI-DSS, FedRAMP&lt;/td&gt;
&lt;td&gt;~$50,000/year&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Snyk Code&lt;/td&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;SAST, SCA&lt;/td&gt;
&lt;td&gt;19+&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;SOC 2&lt;/td&gt;
&lt;td&gt;$25/dev/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Semgrep&lt;/td&gt;
&lt;td&gt;Security + Quality&lt;/td&gt;
&lt;td&gt;SAST, SCA&lt;/td&gt;
&lt;td&gt;30+&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;SOC 2&lt;/td&gt;
&lt;td&gt;Free (OSS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coverity&lt;/td&gt;
&lt;td&gt;Security + Quality&lt;/td&gt;
&lt;td&gt;SAST&lt;/td&gt;
&lt;td&gt;22+&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;SOC 2, PCI-DSS&lt;/td&gt;
&lt;td&gt;~$50,000/year&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fortify&lt;/td&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;SAST, DAST&lt;/td&gt;
&lt;td&gt;25+&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;SOC 2, HIPAA, PCI-DSS&lt;/td&gt;
&lt;td&gt;~$40,000/year&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CodeAnt AI&lt;/td&gt;
&lt;td&gt;Quality + Security&lt;/td&gt;
&lt;td&gt;SAST&lt;/td&gt;
&lt;td&gt;30+&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;SOC 2&lt;/td&gt;
&lt;td&gt;Free (open source)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Codacy&lt;/td&gt;
&lt;td&gt;Quality + Security&lt;/td&gt;
&lt;td&gt;SAST, SCA&lt;/td&gt;
&lt;td&gt;49&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;SOC 2&lt;/td&gt;
&lt;td&gt;$15/user/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSource&lt;/td&gt;
&lt;td&gt;Quality + Security&lt;/td&gt;
&lt;td&gt;SAST&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;SOC 2&lt;/td&gt;
&lt;td&gt;$12/user/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code Climate&lt;/td&gt;
&lt;td&gt;Quality&lt;/td&gt;
&lt;td&gt;SAST&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;SOC 2&lt;/td&gt;
&lt;td&gt;$49/user/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CAST&lt;/td&gt;
&lt;td&gt;Quality + Security&lt;/td&gt;
&lt;td&gt;SAST&lt;/td&gt;
&lt;td&gt;50+&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;SOC 2, HIPAA, PCI-DSS, ISO&lt;/td&gt;
&lt;td&gt;Custom pricing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  1. SonarQube - best overall for combined quality and security audits
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/sonarqube"&gt;SonarQube&lt;/a&gt; is the most widely adopted code audit platform, used by over 400,000 organizations worldwide. It combines code quality analysis with security vulnerability detection in a single platform, making it ideal for teams that want unified audit coverage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it audits:&lt;/strong&gt; Code quality (bugs, code smells, technical debt, code duplication, complexity) and security (OWASP Top 10, CWE Top 25, injection flaws, hardcoded credentials).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analysis type:&lt;/strong&gt; SAST with rule-based pattern matching and dataflow analysis. The Developer Edition and above adds taint analysis for deeper security scanning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 35+ including Java, C#, Python, JavaScript, TypeScript, Go, C/C++, PHP, Ruby, Kotlin, and Swift.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI integration:&lt;/strong&gt; GitHub Actions, GitLab CI, Azure DevOps, Jenkins, Bitbucket Pipelines. Quality gates block merges when thresholds are not met.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance:&lt;/strong&gt; Quality profiles can be mapped to OWASP Top 10 and CWE Top 25. Enterprise Edition provides compliance-specific reporting for SOC 2 and PCI-DSS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Community Build is free and open source. Developer Edition starts at $2,500/year. Enterprise Edition starts at $20,000/year.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Largest rule library with 6,000+ rules across all supported languages&lt;/li&gt;
&lt;li&gt;Quality gate enforcement prevents low-quality code from merging&lt;/li&gt;
&lt;li&gt;Tracks technical debt over time with trend dashboards&lt;/li&gt;
&lt;li&gt;Self-hosted option gives full control over data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Community Edition lacks branch analysis and taint tracking&lt;/li&gt;
&lt;li&gt;Self-hosting requires infrastructure management&lt;/li&gt;
&lt;li&gt;Security analysis depth trails dedicated SAST tools like Checkmarx&lt;/li&gt;
&lt;li&gt;UI can feel dated compared to newer tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams that need a single platform for both code quality metrics and security scanning, especially Java and C# shops.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Checkmarx - best for enterprise security compliance
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/checkmarx"&gt;Checkmarx&lt;/a&gt; is an enterprise application security platform that provides deep security analysis with dedicated compliance reporting. It is the go-to choice for organizations with strict regulatory requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it audits:&lt;/strong&gt; Security only - injection vulnerabilities, authentication flaws, authorization bypasses, cryptographic weaknesses, and 700+ vulnerability categories.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analysis type:&lt;/strong&gt; SAST with advanced taint analysis, SCA for open-source dependencies, and DAST for running applications through Checkmarx DAST.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 25+ including Java, C#, JavaScript, Python, C/C++, PHP, Go, Kotlin, Swift, Ruby, and Scala.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI integration:&lt;/strong&gt; Jenkins, GitHub Actions, GitLab CI, Azure DevOps, Bamboo, TeamCity. Provides IDE plugins for Visual Studio, IntelliJ, VS Code, and Eclipse.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance:&lt;/strong&gt; Dedicated compliance dashboards for SOC 2, HIPAA, PCI-DSS, GDPR, and NIST. Generates audit-ready reports mapped to specific compliance controls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Starts at approximately $40,000/year for small teams. Enterprise contracts typically range from $80,000-150,000+/year depending on developer count and modules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deepest taint analysis in the market catches complex vulnerability chains&lt;/li&gt;
&lt;li&gt;Compliance reporting is audit-ready out of the box&lt;/li&gt;
&lt;li&gt;Unified SAST, SCA, and DAST in one platform&lt;/li&gt;
&lt;li&gt;Dedicated security research team maintains rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expensive - out of reach for small and mid-size teams&lt;/li&gt;
&lt;li&gt;Scan times can be slow for large codebases (30-60+ minutes)&lt;/li&gt;
&lt;li&gt;High false positive rate without tuning (30-50%)&lt;/li&gt;
&lt;li&gt;Steep learning curve for configuration and custom queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Enterprise organizations with dedicated application security teams and compliance requirements like HIPAA, PCI-DSS, or FedRAMP.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Veracode - best for regulated industries
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/veracode"&gt;Veracode&lt;/a&gt; is a cloud-based application security platform that combines SAST, SCA, and DAST with strong compliance support. It is particularly popular in financial services, healthcare, and government sectors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it audits:&lt;/strong&gt; Security - vulnerabilities, insecure coding patterns, open-source license risk, and runtime security issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analysis type:&lt;/strong&gt; SAST (binary analysis and source code analysis), SCA, and DAST. Veracode's binary analysis is unique - it can scan compiled applications without requiring source code access.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 25+ including Java, C#, JavaScript, Python, C/C++, PHP, Go, Ruby, and COBOL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI integration:&lt;/strong&gt; Jenkins, GitHub Actions, GitLab CI, Azure DevOps, Bamboo. Veracode Pipeline Scan provides fast incremental scanning for PRs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance:&lt;/strong&gt; SOC 2, HIPAA, PCI-DSS, FedRAMP, and NIST 800-53. Veracode is FedRAMP authorized, making it one of the few options for US government agencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Starts at approximately $50,000/year. Enterprise contracts range from $100,000-200,000+/year.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FedRAMP authorization makes it viable for government contracts&lt;/li&gt;
&lt;li&gt;Binary analysis works without source code access - useful for third-party code audits&lt;/li&gt;
&lt;li&gt;Veracode Fix provides AI-powered remediation suggestions&lt;/li&gt;
&lt;li&gt;Strong policy engine for enforcing security standards across teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The most expensive tool on this list&lt;/li&gt;
&lt;li&gt;Full platform scans can take hours for large applications&lt;/li&gt;
&lt;li&gt;Pipeline Scan (for fast PR feedback) has a more limited rule set than the full platform scan&lt;/li&gt;
&lt;li&gt;Vendor lock-in risk with proprietary analysis engine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Regulated industries (finance, healthcare, government) that need FedRAMP authorization or binary analysis for third-party code.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Snyk Code - best for developer-friendly security auditing
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/snyk-code"&gt;Snyk Code&lt;/a&gt; is a developer-first SAST tool that prioritizes speed and low false positives. It uses a machine learning engine trained on millions of open-source projects to detect vulnerabilities with strong contextual understanding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it audits:&lt;/strong&gt; Security - injection flaws, hardcoded secrets, insecure data flows, and cryptographic issues. Also includes SCA for dependency vulnerabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analysis type:&lt;/strong&gt; SAST with ML-powered semantic analysis and inter-file dataflow tracking. SCA for open-source components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 19+ including JavaScript, TypeScript, Python, Java, C#, Go, PHP, Ruby, Kotlin, and Swift.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI integration:&lt;/strong&gt; GitHub, GitLab, Bitbucket, Azure DevOps, Jenkins, CircleCI. IDE plugins for VS Code, IntelliJ, and Visual Studio provide real-time scanning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance:&lt;/strong&gt; SOC 2 Type II certified. Findings can be mapped to OWASP Top 10 and CWE Top 25 for compliance evidence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free tier for individual developers (limited scans). Team plan at $25/developer/month. Enterprise pricing is custom.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scan times under 60 seconds for most repositories&lt;/li&gt;
&lt;li&gt;ML-based analysis reduces false positives compared to rule-based tools&lt;/li&gt;
&lt;li&gt;IDE integration catches vulnerabilities before code is committed&lt;/li&gt;
&lt;li&gt;Free tier is genuinely useful for individual developers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Language support is narrower than Checkmarx or SonarQube&lt;/li&gt;
&lt;li&gt;No DAST capability - security-only, no code quality metrics&lt;/li&gt;
&lt;li&gt;Free tier limits the number of scans&lt;/li&gt;
&lt;li&gt;Enterprise pricing can add up quickly for large teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Development teams that want fast, low-noise security scanning integrated directly into their development workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Semgrep - best open-source code audit tool
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/semgrep"&gt;Semgrep&lt;/a&gt; is an open-source static analysis tool with a powerful custom rule engine. It has become the default choice for teams that want deep security scanning with full control over rules and configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it audits:&lt;/strong&gt; Security (injection, XSS, SSRF, secrets, misconfigurations) and code quality (anti-patterns, best practices). The rule registry contains 10,000+ community and pro rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analysis type:&lt;/strong&gt; SAST with pattern matching and cross-file taint analysis (Pro tier). SCA through Semgrep Supply Chain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 30+ including Python, JavaScript, TypeScript, Java, Go, Ruby, PHP, C, C++, Rust, Kotlin, Swift, Terraform, Kubernetes YAML, and Dockerfile.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI integration:&lt;/strong&gt; GitHub Actions, GitLab CI, Jenkins, CircleCI, Bitbucket Pipelines. Single binary - add one line to any CI config.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance:&lt;/strong&gt; Semgrep Pro includes policy engines for enforcing OWASP Top 10 and CWE Top 25. SOC 2 compliant platform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; OSS is completely free. Pro tier is free for teams of 10 or fewer. Paid Pro starts at $35/contributor/month. Enterprise pricing is custom.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OSS version is free for commercial use with 2,800+ community rules&lt;/li&gt;
&lt;li&gt;Custom rules use a simple pattern syntax - no proprietary query language&lt;/li&gt;
&lt;li&gt;Fastest scan times in the category (10-second median)&lt;/li&gt;
&lt;li&gt;Infrastructure-as-code scanning covers Terraform, Kubernetes, and Dockerfiles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OSS version lacks cross-file analysis and taint tracking&lt;/li&gt;
&lt;li&gt;Code quality rules are less comprehensive than SonarQube&lt;/li&gt;
&lt;li&gt;Pro tier's per-contributor pricing can get expensive for large teams&lt;/li&gt;
&lt;li&gt;No built-in compliance reporting dashboards&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams that want a powerful, customizable security audit tool without vendor lock-in, especially those with infrastructure-as-code to scan.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Coverity - best for C/C++ and embedded systems
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/coverity"&gt;Coverity&lt;/a&gt; (by Synopsys) is an enterprise SAST tool known for its deep analysis of compiled languages. It is the industry standard for auditing C, C++, and embedded systems code where memory safety and reliability are critical.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it audits:&lt;/strong&gt; Security vulnerabilities and code quality defects including memory leaks, null pointer dereferences, buffer overflows, race conditions, and resource leaks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analysis type:&lt;/strong&gt; SAST with interprocedural dataflow analysis, abstract interpretation, and path-sensitive analysis. Coverity's analysis engine understands complex control flow in ways that lighter tools cannot match.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 22+ with the deepest analysis for C, C++, Java, and C#. Also supports JavaScript, Python, Go, Ruby, PHP, Kotlin, and Swift.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI integration:&lt;/strong&gt; Jenkins, GitHub Actions, GitLab CI, Azure DevOps, Bamboo. Coverity Connect provides a centralized web dashboard for managing findings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance:&lt;/strong&gt; Findings mapped to CWE, OWASP Top 10, CERT C/C++, MISRA, and DISA STIG. Used extensively in automotive (ISO 26262), aerospace, and medical device development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Starts at approximately $50,000/year. Enterprise contracts range from $75,000-100,000+/year.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deepest C/C++ analysis in the market - catches issues other tools miss&lt;/li&gt;
&lt;li&gt;Path-sensitive analysis reduces false positives on complex control flow&lt;/li&gt;
&lt;li&gt;Industry-standard for safety-critical systems (automotive, medical, aerospace)&lt;/li&gt;
&lt;li&gt;Low false positive rate for compiled languages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expensive - enterprise-only pricing&lt;/li&gt;
&lt;li&gt;Scan times are the slowest on this list for large codebases&lt;/li&gt;
&lt;li&gt;Web interface feels dated&lt;/li&gt;
&lt;li&gt;Limited value for interpreted languages compared to competitors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Organizations developing in C/C++ or building safety-critical embedded systems that need the deepest possible static analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Fortify - best for comprehensive security audit coverage
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/fortify"&gt;Fortify&lt;/a&gt; (by OpenText, formerly Micro Focus/HPE) is an enterprise SAST platform with one of the largest vulnerability rule databases in the industry. It covers both source code analysis and runtime testing through Fortify WebInspect (DAST).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it audits:&lt;/strong&gt; Security - 1,000+ vulnerability categories including OWASP Top 10, CWE/SANS Top 25, DISA STIG, and PCI-DSS-specific checks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analysis type:&lt;/strong&gt; SAST with deep dataflow analysis and taint tracking. DAST through Fortify WebInspect (sold separately). Software Composition Analysis through Sonatype integration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 25+ including Java, C#, JavaScript, Python, C/C++, PHP, Go, Ruby, ABAP, COBOL, and Apex (Salesforce).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI integration:&lt;/strong&gt; Jenkins, Azure DevOps, GitHub Actions, GitLab CI, Bamboo. Fortify on Demand provides a cloud-hosted SaaS option.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance:&lt;/strong&gt; Dedicated compliance reporting for SOC 2, HIPAA, PCI-DSS, NIST 800-53, and DISA STIG. Findings map directly to regulatory controls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; On-premises licensing starts at approximately $40,000/year. Fortify on Demand (cloud) pricing is custom based on application count and scan frequency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Largest vulnerability rule database with 1,000+ categories&lt;/li&gt;
&lt;li&gt;Supports legacy languages (COBOL, ABAP) that other tools do not&lt;/li&gt;
&lt;li&gt;Fortify on Demand provides managed cloud scanning without infrastructure&lt;/li&gt;
&lt;li&gt;Strong government and defense sector adoption&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High false positive rate requires dedicated triage effort&lt;/li&gt;
&lt;li&gt;On-premises deployment is complex&lt;/li&gt;
&lt;li&gt;UI and developer experience lag behind modern tools&lt;/li&gt;
&lt;li&gt;Expensive licensing model&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Large enterprises with diverse technology stacks including legacy languages, and organizations in government or defense sectors.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. CodeAnt AI - best free code audit tool for startups
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/codeant-ai"&gt;CodeAnt AI&lt;/a&gt; is an AI-powered code quality and security platform that provides automated code audits with a generous free tier. It focuses on detecting anti-patterns, security issues, and code quality problems using static analysis combined with AI-driven insights.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it audits:&lt;/strong&gt; Code quality (anti-patterns, dead code, code duplication, complexity) and security (common vulnerability patterns, dependency risks).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analysis type:&lt;/strong&gt; SAST with AI-augmented pattern detection. Focuses on code quality issues and common security patterns rather than deep taint analysis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 30+ including Python, JavaScript, TypeScript, Java, Go, Ruby, PHP, C#, Kotlin, Swift, and Rust.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI integration:&lt;/strong&gt; GitHub, GitLab, Bitbucket. Provides PR-level feedback and repository-wide scanning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance:&lt;/strong&gt; SOC 2 evidence collection through security scanning. No dedicated compliance dashboards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free for open-source projects. Free tier available for small teams. Paid plans start at $10/user/month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generous free tier makes it accessible to startups and small teams&lt;/li&gt;
&lt;li&gt;AI-driven detection catches issues traditional linters miss&lt;/li&gt;
&lt;li&gt;Fast scan times with minimal configuration&lt;/li&gt;
&lt;li&gt;Supports a wide range of languages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security analysis is not as deep as dedicated SAST tools like Checkmarx or Fortify&lt;/li&gt;
&lt;li&gt;Newer tool with a smaller community and rule library&lt;/li&gt;
&lt;li&gt;Limited compliance reporting capabilities&lt;/li&gt;
&lt;li&gt;Enterprise features are still maturing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Startups and small teams that want automated code quality and security auditing without the cost of enterprise tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Codacy - best for polyglot teams
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/codacy"&gt;Codacy&lt;/a&gt; supports 49 programming languages - more than any other tool on this list. It combines code quality analysis with security scanning and provides a unified dashboard for tracking audit metrics across repositories.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it audits:&lt;/strong&gt; Code quality (complexity, duplication, coding standards, coverage tracking) and security (OWASP Top 10, common vulnerabilities, dependency scanning).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analysis type:&lt;/strong&gt; SAST using multiple open-source engines (ESLint, PMD, Pylint, Bandit, and others) plus proprietary patterns. SCA for dependency vulnerabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 49 including JavaScript, TypeScript, Python, Java, C#, Go, Ruby, PHP, Scala, Kotlin, Swift, Rust, Haskell, Dart, and many more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI integration:&lt;/strong&gt; GitHub, GitLab, Bitbucket. Webhook-based - scans automatically on every push and PR. Also supports Jenkins and CircleCI through CLI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance:&lt;/strong&gt; SOC 2 Type II certified. Security scanning results support compliance evidence collection. Business plan adds DAST capabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free for open source. Pro plan at $15/user/month. Business plan with DAST and advanced security at custom pricing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Widest language support at 49 languages&lt;/li&gt;
&lt;li&gt;Aggregates multiple analysis engines for broader coverage&lt;/li&gt;
&lt;li&gt;Coverage tracking and quality metrics in one platform&lt;/li&gt;
&lt;li&gt;Affordable pricing for small and mid-size teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jack-of-all-trades - security depth trails dedicated SAST tools&lt;/li&gt;
&lt;li&gt;Some language analyzers are shallow (basic linting only)&lt;/li&gt;
&lt;li&gt;Dashboard can be slow with many repositories&lt;/li&gt;
&lt;li&gt;Limited custom rule authoring compared to Semgrep&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Polyglot teams using many languages that want unified quality and security metrics in a single affordable platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. DeepSource - best for automated fix suggestions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/tools/deepsource"&gt;DeepSource&lt;/a&gt; combines static analysis with automated fix suggestions (Autofix) that can resolve detected issues with one click. It is particularly strong on code quality with a growing security capability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it audits:&lt;/strong&gt; Code quality (anti-patterns, bug risks, style violations, complexity, coverage) and security (common vulnerabilities, secrets detection, dependency scanning).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analysis type:&lt;/strong&gt; SAST with dataflow analysis. Proprietary analysis engine built from scratch rather than wrapping open-source tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 16 including Python, JavaScript, TypeScript, Java, Go, Ruby, PHP, C#, Kotlin, Swift, Rust, and Scala.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI integration:&lt;/strong&gt; GitHub, GitLab, Bitbucket. Automatic scanning on every commit and PR. Also provides a CLI for local scanning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance:&lt;/strong&gt; SOC 2 Type II certified. Security findings support compliance evidence collection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free for open source and individuals. Team plan at $12/user/month. Enterprise pricing is custom.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Autofix resolves many issues automatically - saves remediation time&lt;/li&gt;
&lt;li&gt;Sub-5% false positive rate - the lowest in the category&lt;/li&gt;
&lt;li&gt;Clean, modern UI with excellent developer experience&lt;/li&gt;
&lt;li&gt;Most affordable paid tier at $12/user/month&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supports only 16 languages - the fewest on this list&lt;/li&gt;
&lt;li&gt;Security analysis is less comprehensive than dedicated SAST tools&lt;/li&gt;
&lt;li&gt;No DAST or advanced taint analysis&lt;/li&gt;
&lt;li&gt;Enterprise features are still developing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams that want low-noise code quality auditing with automated remediation at an affordable price.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Code Climate - best for engineering team metrics
&lt;/h2&gt;

&lt;p&gt;Code Climate focuses on code quality metrics and engineering team productivity. It is less of a security audit tool and more of a quality and maintainability audit platform. Code Climate Quality analyzes code for complexity, duplication, and maintainability issues while Code Climate Velocity tracks engineering team metrics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it audits:&lt;/strong&gt; Code quality only - maintainability, complexity, duplication, test coverage, and coding standards. No security vulnerability detection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analysis type:&lt;/strong&gt; SAST for code quality metrics. Uses maintainability ratings (A through F) for quick assessment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 17 including JavaScript, TypeScript, Python, Ruby, Go, Java, PHP, C#, and Swift.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI integration:&lt;/strong&gt; GitHub and GitLab. PR-level feedback with status checks. Jenkins integration available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance:&lt;/strong&gt; SOC 2 certified. Quality metrics support general compliance evidence but no security-specific compliance reporting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Quality starts at $49/user/month. Velocity (engineering metrics) is priced separately. Combined plans available at custom pricing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintainability ratings provide instant codebase health assessment&lt;/li&gt;
&lt;li&gt;Engineering velocity metrics help identify process bottlenecks&lt;/li&gt;
&lt;li&gt;Clean PR integration with pass/fail quality gates&lt;/li&gt;
&lt;li&gt;Good for non-technical stakeholders who need simple quality metrics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No security scanning at all - must pair with a separate security tool&lt;/li&gt;
&lt;li&gt;Expensive for what it offers at $49/user/month&lt;/li&gt;
&lt;li&gt;Limited language support compared to competitors&lt;/li&gt;
&lt;li&gt;Quality analysis is less detailed than SonarQube&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Engineering leaders who need maintainability metrics and team productivity data for quality-focused audits.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. CAST - best for large-scale enterprise code audits
&lt;/h2&gt;

&lt;p&gt;CAST (CAST Highlight and CAST Imaging) specializes in large-scale codebase analysis for enterprise transformation, due diligence, and portfolio-level audits. It can analyze millions of lines of code across 50+ languages and provides architectural visualization alongside quality and security metrics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it audits:&lt;/strong&gt; Code quality (technical debt, complexity, maintainability), security (OWASP, CWE), and architecture (dependency mapping, component coupling, cloud readiness).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analysis type:&lt;/strong&gt; SAST with architectural analysis. CAST Imaging creates interactive architecture maps from source code. CAST Highlight provides portfolio-level metrics across hundreds of applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Languages:&lt;/strong&gt; 50+ including Java, C#, JavaScript, Python, C/C++, COBOL, ABAP, PL/SQL, RPG, and dozens of legacy languages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI integration:&lt;/strong&gt; CAST can integrate with CI/CD pipelines but is primarily designed for periodic comprehensive audits rather than PR-level scanning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance:&lt;/strong&gt; SOC 2, HIPAA, PCI-DSS, ISO 27001. Generates audit-ready compliance reports. Used extensively in M&amp;amp;A due diligence by Big Four consulting firms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Custom pricing based on lines of code and application count. Typical engagements range from $30,000-200,000+ per year.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handles the largest codebases (millions of lines across hundreds of applications)&lt;/li&gt;
&lt;li&gt;Architectural visualization is unique - no other tool provides this&lt;/li&gt;
&lt;li&gt;Portfolio-level analysis across entire application estates&lt;/li&gt;
&lt;li&gt;Strong M&amp;amp;A and due diligence track record&lt;/li&gt;
&lt;li&gt;Best legacy language support on this list&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not designed for developer workflow integration (PR-level scanning)&lt;/li&gt;
&lt;li&gt;Expensive and complex to deploy&lt;/li&gt;
&lt;li&gt;Overkill for small and mid-size organizations&lt;/li&gt;
&lt;li&gt;Learning curve for interpreting architectural analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Large enterprises conducting portfolio-level audits, M&amp;amp;A due diligence, or modernization assessments across diverse technology stacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommendations by use case
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For startups and small teams (under 20 developers)
&lt;/h3&gt;

&lt;p&gt;Start with &lt;strong&gt;Semgrep OSS&lt;/strong&gt; for security scanning and &lt;strong&gt;SonarQube Community Build&lt;/strong&gt; for code quality. Both are free. Add &lt;strong&gt;DeepSource&lt;/strong&gt; ($12/user/month) or &lt;strong&gt;CodeAnt AI&lt;/strong&gt; (free tier) if you want a managed platform with less configuration overhead. This stack covers security and quality auditing at minimal cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  For mid-size teams (20-100 developers)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Semgrep Pro&lt;/strong&gt; (free for 10 contributors, then $35/contributor/month) provides the strongest security coverage. Pair with &lt;strong&gt;Codacy&lt;/strong&gt; ($15/user/month) for broad language support and quality metrics. If you prefer a single tool, &lt;strong&gt;SonarQube Developer Edition&lt;/strong&gt; ($2,500/year) provides unified quality and security at reasonable cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  For enterprise security compliance
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Checkmarx&lt;/strong&gt; or &lt;strong&gt;Veracode&lt;/strong&gt; for organizations that need dedicated compliance reporting, SAST + SCA + DAST in one platform, and audit-ready documentation. Choose Veracode if you need FedRAMP authorization or binary analysis. Choose Checkmarx for the deepest taint analysis.&lt;/p&gt;

&lt;h3&gt;
  
  
  For C/C++ and embedded systems
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Coverity&lt;/strong&gt; is the clear choice. Its path-sensitive analysis and understanding of memory safety issues in C/C++ are unmatched. Supplement with &lt;strong&gt;SonarQube&lt;/strong&gt; for broader quality metrics.&lt;/p&gt;

&lt;h3&gt;
  
  
  For M&amp;amp;A due diligence and portfolio audits
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;CAST&lt;/strong&gt; is purpose-built for this use case. Its ability to analyze millions of lines across 50+ languages and generate architectural visualizations makes it the standard for technical due diligence.&lt;/p&gt;

&lt;h3&gt;
  
  
  For developer-first security
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Snyk Code&lt;/strong&gt; provides the fastest feedback loop with IDE integration and sub-60-second scan times. Pair with &lt;strong&gt;Semgrep&lt;/strong&gt; for deeper custom rule coverage. This combination gives developers real-time security feedback without disrupting their workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key factors when choosing a code audit tool
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Analysis depth vs speed
&lt;/h3&gt;

&lt;p&gt;Enterprise tools like Checkmarx and Coverity perform deep interprocedural analysis that catches complex vulnerability chains but takes 30-60+ minutes. Tools like Semgrep and Snyk Code scan in seconds but may miss vulnerabilities that require deep path analysis. For continuous auditing in CI/CD, speed matters. For periodic comprehensive audits, depth matters more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compliance requirements
&lt;/h3&gt;

&lt;p&gt;If your organization needs compliance-specific reporting (SOC 2, HIPAA, PCI-DSS), enterprise tools like Checkmarx, Veracode, and Fortify provide audit-ready dashboards out of the box. Open-source tools like Semgrep and SonarQube can support compliance evidence collection but require more manual effort to produce audit-ready reports.&lt;/p&gt;

&lt;h3&gt;
  
  
  Language coverage
&lt;/h3&gt;

&lt;p&gt;Verify that your primary languages have deep analysis support, not just surface-level linting. A tool that lists 50 languages but only has deep analysis for 5 of them may miss critical issues in your stack. SonarQube has the deepest Java and C# analysis. Coverity leads for C/C++. Semgrep is strongest for Python and Go security.&lt;/p&gt;

&lt;h3&gt;
  
  
  False positive management
&lt;/h3&gt;

&lt;p&gt;High false positive rates destroy developer trust and make audit findings useless. DeepSource claims a sub-5% false positive rate. Snyk Code and Semgrep with AI triage achieve low false positive rates. Enterprise tools like Checkmarx and Fortify can have 30-50% false positive rates without tuning. Ask for trial access and test on your actual codebase before committing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Total cost of ownership
&lt;/h3&gt;

&lt;p&gt;Free tools still have costs - infrastructure, configuration, and maintenance time. A managed SaaS tool at $15/user/month may be cheaper than self-hosting a free tool when you account for engineering time. Factor in training, rollout, and ongoing rule maintenance when comparing pricing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final verdict
&lt;/h2&gt;

&lt;p&gt;There is no single best code audit tool because the right choice depends on your team size, technology stack, compliance requirements, and budget. For most teams, a combination of two tools provides the best coverage:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A security-focused tool&lt;/strong&gt; (Semgrep, Snyk Code, or Checkmarx depending on budget) for vulnerability detection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A quality-focused tool&lt;/strong&gt; (SonarQube, Codacy, or DeepSource) for technical debt, complexity, and maintainability tracking&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Run the security tool in every CI pipeline for continuous protection. Run the quality tool for periodic comprehensive audits and trend tracking. This two-tool approach covers both dimensions of code auditing - security and quality - without overloading developers with a single monolithic platform.&lt;/p&gt;

&lt;p&gt;The most important thing is to start auditing. A simple Semgrep + SonarQube setup running in CI catches more issues than a perfectly planned enterprise audit program that never gets deployed. Start with what you can implement this week and iterate from there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is a code audit?
&lt;/h3&gt;

&lt;p&gt;A code audit is a systematic review of source code to evaluate its quality, security, maintainability, and compliance with coding standards. Unlike routine code review during pull requests, a code audit examines the entire codebase or a significant portion of it to identify systemic issues - security vulnerabilities, technical debt, architectural weaknesses, and violations of regulatory requirements like SOC 2, HIPAA, or PCI-DSS. Code audits can be performed internally by the development team or externally by third-party firms.&lt;/p&gt;

&lt;h3&gt;
  
  
  How often should you perform a code audit?
&lt;/h3&gt;

&lt;p&gt;Most organizations should perform a comprehensive code audit at least once per year, with automated scanning running continuously in CI/CD pipelines. High-risk events that should trigger an immediate audit include pre-acquisition due diligence, major architecture changes, compliance certification renewals, post-security-incident reviews, and onboarding a new development team or vendor. Continuous automated auditing with tools like SonarQube or Semgrep supplements annual deep audits by catching issues in real time.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the difference between a code audit and a code review?
&lt;/h3&gt;

&lt;p&gt;A code review evaluates individual changes at the pull request level, focusing on whether new or modified code is correct and follows team conventions. A code audit is a broader examination of the entire codebase or a major subsystem, looking for systemic patterns like accumulated technical debt, widespread security weaknesses, licensing violations, and compliance gaps. Code reviews are ongoing and incremental. Code audits are periodic and comprehensive. Both are necessary for a mature engineering organization.&lt;/p&gt;

&lt;h3&gt;
  
  
  How much do code audit tools cost?
&lt;/h3&gt;

&lt;p&gt;Code audit tool pricing ranges from free to over $200,000 per year. Free options include SonarQube Community Build, Semgrep OSS, and DeepSource's free tier. Mid-range tools cost $12-35 per developer per month - DeepSource at $12/user/month, Codacy at $15/user/month, and Semgrep at $35/contributor/month. Enterprise tools like Checkmarx ($40,000-150,000+/year), Veracode ($50,000-200,000+/year), Fortify ($40,000-80,000+/year), and Coverity ($50,000-100,000+/year) include compliance reporting and dedicated support.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can automated code audit tools replace manual audits?
&lt;/h3&gt;

&lt;p&gt;No. Automated tools excel at detecting known vulnerability patterns, coding standard violations, and quantifiable metrics like cyclomatic complexity and code duplication. However, they cannot evaluate business logic correctness, architectural soundness, or whether the code actually meets its intended requirements. A thorough code audit combines automated tooling for breadth and speed with manual expert review for depth and context. The best approach is to run automated scans first to clear the mechanical issues, then have human auditors focus on architecture, logic, and design.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which code audit tools support SOC 2 and PCI-DSS compliance?
&lt;/h3&gt;

&lt;p&gt;Enterprise tools like Checkmarx, Veracode, Fortify, and Coverity provide dedicated compliance reporting for SOC 2, PCI-DSS, HIPAA, and other regulatory frameworks. They map findings directly to compliance controls and generate audit-ready reports. SonarQube Developer Edition and above includes compliance-oriented quality profiles. Semgrep and Snyk Code offer policy engines that can enforce compliance-related rules. For smaller teams, Codacy and DeepSource provide security scanning that supports SOC 2 evidence collection, though without the dedicated compliance dashboards of enterprise tools.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://aicodereview.cc/blog/best-code-audit-tools/" rel="noopener noreferrer"&gt;aicodereview.cc&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>ai</category>
      <category>programming</category>
      <category>tools</category>
    </item>
  </channel>
</rss>
