<?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: Prateek Singh</title>
    <description>The latest articles on DEV Community by Prateek Singh (@prateek_kumar_singh).</description>
    <link>https://dev.to/prateek_kumar_singh</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4155828%2F988a065e-d552-460d-a365-6ad232ea71a8.jpeg</url>
      <title>DEV Community: Prateek Singh</title>
      <link>https://dev.to/prateek_kumar_singh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/prateek_kumar_singh"/>
    <language>en</language>
    <item>
      <title>Cloudcraft vs Hava vs Cloudeval AI: which diagram tool, when?</title>
      <dc:creator>Prateek Singh</dc:creator>
      <pubDate>Tue, 20 Oct 2026 15:07:52 +0000</pubDate>
      <link>https://dev.to/cloudeval-ai/cloudcraft-vs-hava-vs-cloudeval-ai-which-diagram-tool-when-3l38</link>
      <guid>https://dev.to/cloudeval-ai/cloudcraft-vs-hava-vs-cloudeval-ai-which-diagram-tool-when-3l38</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Cloudcraft, Hava and Cloudeval AI all draw cloud diagrams, but they answer different questions. Cloudcraft designs diagrams and, inside Datadog, shows live infrastructure with ops overlays. Hava auto-documents connected AWS, GCP and Azure accounts with version history and change alerts. Cloudeval AI reviews an Azure ARM or compiled Bicep change in the pull request, before deployment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;By Prateek Singh, founder of Ganak AI Labs. Updated 6 October 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;"Which cloud diagram tool should we use?" usually gets answered with a feature checklist. That's the wrong frame. Tools that all draw a nice picture often solve different problems.&lt;/p&gt;

&lt;p&gt;A better split is the three questions teams ask, at three different times:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;"What does it look like?"&lt;/strong&gt; You're designing, presenting or onboarding someone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"What's running, and what changed?"&lt;/strong&gt; You're documenting, auditing or debugging the live estate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Is this change safe to ship?"&lt;/strong&gt; A pull request is open and nothing is deployed yet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That third job is pre-deployment review: checking a change's design, cost and security before it ships. Cloudcraft, Hava and Cloudeval each lean toward a different question.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I'm the founder of Cloudeval. The Cloudcraft and Hava sections stick to what their own sites say, with links. Prices change, so check before you buy.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Cloudcraft best for? Design and live diagrams in Datadog
&lt;/h2&gt;

&lt;p&gt;Cloudcraft is now part of Datadog and comes in two forms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloudcraft in Datadog&lt;/strong&gt; is a live, read-only view of AWS, Azure, GCP, OCI and vSphere resources (&lt;a href="https://docs.datadoghq.com/datadog_cloudcraft/" rel="noopener noreferrer"&gt;Datadog docs&lt;/a&gt;). You can switch overlays for infrastructure, observability, security, cloud cost and APM (AWS only, preview).&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.cloudcraft.co/" rel="noopener noreferrer"&gt;Cloudcraft homepage&lt;/a&gt; pitches alerts, logs, security findings and costs on a diagram that updates as your infrastructure changes. Some overlays need other Datadog products, such as Cloud Security for the security overlay. It's free with any Datadog subscription (&lt;a href="https://www.cloudcraft.co/pricing" rel="noopener noreferrer"&gt;pricing&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloudcraft (Standalone)&lt;/strong&gt; is a diagramming tool for AWS and Azure, with 3D views of your environments (&lt;a href="https://docs.datadoghq.com/cloudcraft/" rel="noopener noreferrer"&gt;docs&lt;/a&gt;). Two features stand out for design work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live and snapshot diagrams.&lt;/strong&gt; A live diagram updates from your account. A snapshot is static and fully editable, and you can add components from the Design tab (&lt;a href="https://docs.datadoghq.com/cloudcraft/getting-started/live-vs-snapshot-diagrams/" rel="noopener noreferrer"&gt;docs&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blueprints&lt;/strong&gt;, which hold "your diagram, a budget, and all the documentation you attach to individual components" (&lt;a href="https://docs.datadoghq.com/cloudcraft/getting-started/create-your-first-cloudcraft-diagram/" rel="noopener noreferrer"&gt;docs&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Connecting an Azure account to standalone Cloudcraft needs a Pro subscription (&lt;a href="https://docs.datadoghq.com/cloudcraft/getting-started/connect-azure-account-with-cloudcraft/" rel="noopener noreferrer"&gt;docs&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it shines:&lt;/strong&gt; whiteboard-quality design diagrams, budgeting a proposed architecture and, on Datadog, ops context on the live picture during incidents.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Hava best for? Auto-generated diagrams and drift alerts
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.hava.io/" rel="noopener noreferrer"&gt;Hava&lt;/a&gt; connects to your AWS, GCP and Azure accounts and generates interactive diagrams "grouped by VPCs or resource zones." Its homepage lists:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;security view&lt;/strong&gt; of security groups, route tables and connections, to help catch public access to internal services and overly permissive rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost forecasts&lt;/strong&gt; by VPC, region, instance, tag or project. Hava says plainly that it "isn't a replacement for billing platforms."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versioning.&lt;/strong&gt; Hava polls your cloud config, archives old diagram versions and lets you compare them over time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alerts&lt;/strong&gt; when infrastructure changes.&lt;/li&gt;
&lt;li&gt;Exports to Visio, PNG, CSV or JSON, embeddable diagrams and a self-hosted option.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For automation, Hava publishes a GitHub Action, &lt;a href="https://github.com/teamhava/hava-sync-action" rel="noopener noreferrer"&gt;&lt;code&gt;teamhava/hava-sync-action&lt;/code&gt;&lt;/a&gt;, to "synchronize and export a diagram after you have deployed changes to your environment". It writes a PNG to your repo.&lt;/p&gt;

&lt;p&gt;Every &lt;a href="https://www.hava.io/pricing" rel="noopener noreferrer"&gt;Hava plan&lt;/a&gt; includes unlimited diagrams, daily sync and 3, 6 or 12 months of history. The two-week trial includes Teams features, with exports off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it shines:&lt;/strong&gt; always-current documentation of what's deployed across several clouds, with history and drift alerts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Cloudeval AI best for? Reviewing a change before deploy
&lt;/h2&gt;

&lt;p&gt;Cloudeval can start from the template in your pull request instead of a connected account, before anything is deployed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fojzbxh2opwdfhnl004cx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fojzbxh2opwdfhnl004cx.png" alt="Cloudeval Quick Project Creation dialog importing a GitHub-hosted ARM template URL, with stages for connection, file import, stack resolution and diagram and report generation" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Importing a GitHub-hosted ARM template into a project.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inputs:&lt;/strong&gt; ARM JSON, Bicep compiled to ARM JSON, and AWS CloudFormation JSON or YAML as a static beta. For what's already running, live Azure comes in through Cloud sync with a least-privilege, resource-group-scoped custom role (&lt;a href="https://docs.cloudeval.ai/trust/supported-clouds-and-iac?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=diagramming-vs-predeploy&amp;amp;utm_content=support" rel="noopener noreferrer"&gt;support matrix&lt;/a&gt;). There's no live AWS or GCP connection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output:&lt;/strong&gt; architecture and dependency views, cost estimates, Well-Architected and validation results, and findings tied to the affected resource. Findings draw on 1,650+ checks. Not every project runs every check, and unsupported areas show as &lt;code&gt;Not assessed&lt;/code&gt; instead of passing silently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In the PR:&lt;/strong&gt; a GitHub Action posts one result comment. It can fail the job on thresholds you set for Well-Architected score, high-risk findings, validation and monthly cost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handoff:&lt;/strong&gt; the CLI exports diagrams as PNG, JPEG or SVG, which also works for CI or agents.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo4exvf9iddpifc0axi57.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo4exvf9iddpifc0axi57.jpeg" alt="Cloudeval cloud evaluation report overview with posture score, critical risk count, run-rate cost, savings, maturity score and priority decisions" width="800" height="458"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Posture, critical issues, cost and priorities on one screen.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It isn't a freeform design canvas, an observability overlay or a multi-cloud live inventory. PR diagram diffs and snapshot drift comparison are planned, not shipped yet (&lt;a href="https://docs.cloudeval.ai/trust/interfaces-and-workflows?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=diagramming-vs-predeploy&amp;amp;utm_content=roadmap" rel="noopener noreferrer"&gt;interfaces and workflows&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it shines:&lt;/strong&gt; the gap between "the template is valid" and "the template is deployed", when a reviewer wants the shape, cost and risk of a change.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fas01q1srkgj0m87u3dps.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fas01q1srkgj0m87u3dps.jpeg" alt="Cloudeval architecture view with issue badges, dependency labels, cost status and project-aware AI chat" width="800" height="457"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Architecture view with issue badges, dependency labels and cost status.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The difference is the link from a finding to what it affects. This 48-second clip shows it:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/ozl0jQhoXqM" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  How do Cloudcraft, Hava and Cloudeval AI compare?
&lt;/h2&gt;

&lt;p&gt;This maps what each tool is built for, from each vendor's own description. It's not a scorecard.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Cloudcraft&lt;/th&gt;
&lt;th&gt;Hava&lt;/th&gt;
&lt;th&gt;Cloudeval&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Primary question&lt;/td&gt;
&lt;td&gt;What does it look like? What's happening now (in Datadog)?&lt;/td&gt;
&lt;td&gt;What's deployed, and what changed?&lt;/td&gt;
&lt;td&gt;Is this change safe to ship?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Starts from&lt;/td&gt;
&lt;td&gt;Connected accounts (live) or a hand-built design (snapshot)&lt;/td&gt;
&lt;td&gt;Connected cloud accounts&lt;/td&gt;
&lt;td&gt;A template in a PR, or a live Azure sync&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Providers (per vendor)&lt;/td&gt;
&lt;td&gt;In Datadog: AWS, Azure, GCP, OCI, vSphere. Standalone: AWS, Azure&lt;/td&gt;
&lt;td&gt;AWS, GCP, Azure&lt;/td&gt;
&lt;td&gt;Azure, plus AWS CloudFormation (beta)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Design and editing&lt;/td&gt;
&lt;td&gt;Snapshot diagrams, Design tab, blueprints with budget&lt;/td&gt;
&lt;td&gt;Not the focus of its main pages&lt;/td&gt;
&lt;td&gt;Markup on generated diagrams, not a freeform canvas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Change over time&lt;/td&gt;
&lt;td&gt;Diagram version history&lt;/td&gt;
&lt;td&gt;Version history, diagram comparison, change alerts&lt;/td&gt;
&lt;td&gt;Per-commit PR reviews. Drift and graph diff are planned&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Blueprint budgets, Cloud Cost overlay in Datadog&lt;/td&gt;
&lt;td&gt;Cost forecasts&lt;/td&gt;
&lt;td&gt;Monthly cost estimate and an optional budget gate in the PR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security signal&lt;/td&gt;
&lt;td&gt;Security overlay (needs Datadog Cloud Security)&lt;/td&gt;
&lt;td&gt;Security view of groups, routes and exposure&lt;/td&gt;
&lt;td&gt;Findings with evidence from 1,650+ checks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CI/CD&lt;/td&gt;
&lt;td&gt;Not covered here&lt;/td&gt;
&lt;td&gt;GitHub Action and CLI to sync and export after deploy&lt;/td&gt;
&lt;td&gt;GitHub Action that comments and gates before merge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pricing (per vendor page)&lt;/td&gt;
&lt;td&gt;Free with any Datadog subscription&lt;/td&gt;
&lt;td&gt;From $59/month&lt;/td&gt;
&lt;td&gt;Free 7-day trial (150 credits), Basic $19/month, Pro $49/month&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmgqmfvocifiz4bzsbzlm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmgqmfvocifiz4bzsbzlm.png" alt="Cloudeval report treemap grouping findings by resource type, with Virtual Machines, Storage Accounts, Load Balancers and Virtual Networks as the largest tiles" width="800" height="470"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The treemap shows where findings cluster by resource type.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Can you use Cloudcraft or Hava with Cloudeval AI?
&lt;/h2&gt;

&lt;p&gt;Yes, and that's often the most practical setup. This pipeline reviews on the pull request, then refreshes documentation diagrams after deploy.&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/infra.yml (sketch: wire in your own deploy job)&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;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
  &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
  &lt;span class="na"&gt;issues&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&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;pre-deploy-review&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;            &lt;span class="c1"&gt;# Question 3: is this change safe to ship?&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;github.event_name == 'pull_request'&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;ganakailabs/cloudeval-action@v1&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;access_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.CLOUDEVAL_ACCESS_KEY }}&lt;/span&gt;
          &lt;span class="na"&gt;project_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.CLOUDEVAL_PROJECT_ID }}&lt;/span&gt;
          &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;review&lt;/span&gt;
          &lt;span class="na"&gt;post_pr_comment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;upload_artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="c1"&gt;# deploy: ...                 # your existing deployment job&lt;/span&gt;

  &lt;span class="na"&gt;refresh-docs-diagram&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;         &lt;span class="c1"&gt;# Question 2: what's deployed now?&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;github.event_name == 'push'&lt;/span&gt;
    &lt;span class="c1"&gt;# needs: deploy&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;teamhava/hava-sync-action@v1&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;source_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.HAVA_SOURCE_ID }}&lt;/span&gt;
          &lt;span class="na"&gt;hava_token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.HAVA_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;environment_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.HAVA_ENVIRONMENT_ID }}&lt;/span&gt;
          &lt;span class="na"&gt;view_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;infrastructure&lt;/span&gt;
          &lt;span class="na"&gt;image_path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docs/architecture.png&lt;/span&gt;
      &lt;span class="c1"&gt;# commit docs/architecture.png in a follow-up step if you want it in the repo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Cloudeval job needs the repo linked through the Cloudeval GitHub App. The Hava job needs a connected Hava source. On Datadog, Cloudcraft's live diagram replaces the second job, outside CI entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which cloud diagram tool should you choose?
&lt;/h2&gt;

&lt;p&gt;Ask these in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Designing something new and presenting it?&lt;/strong&gt; Cloudcraft's snapshot diagrams and blueprints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Already paying for Datadog?&lt;/strong&gt; Cloudcraft in Datadog is included.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Need always-current docs and change history across AWS, GCP and Azure?&lt;/strong&gt; That's Hava's core pitch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Changes reach production through pull requests, and nobody checks design, cost and exposure there?&lt;/strong&gt; That's the gap Cloudeval targets.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some teams answer "yes" to two. That's fine, because the tools mostly don't compete for the same moment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is a good Cloudcraft alternative for Azure?
&lt;/h3&gt;

&lt;p&gt;It depends on the job. Hava is built for always-current documentation and change history of deployed Azure, AWS and GCP accounts. Cloudeval AI reviews an Azure ARM or compiled Bicep change in a pull request before it ships. See the longer &lt;a href="https://cloudeval.ai/compare/cloudcraft-alternative?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=diagramming-vs-predeploy&amp;amp;utm_content=faq" rel="noopener noreferrer"&gt;Cloudcraft alternative for Azure pre-deployment review&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does Cloudcraft support Azure?
&lt;/h3&gt;

&lt;p&gt;Yes. Per Datadog's docs, Cloudcraft (Standalone) covers AWS and Azure, and connecting an Azure account needs a Pro subscription. Cloudcraft in Datadog covers AWS, Azure, GCP, OCI and vSphere.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is Cloudcraft free?
&lt;/h3&gt;

&lt;p&gt;Cloudcraft's pricing page says it's free with any Datadog subscription, with unlimited users and diagrams. Standalone Cloudcraft has Free, Pro and Enterprise plans, and connecting Azure needs Pro.&lt;/p&gt;

&lt;h3&gt;
  
  
  How much does Hava cost?
&lt;/h3&gt;

&lt;p&gt;Hava's pricing page lists Professional at $59/month (3 cloud accounts, 1 user), Teams at $249/month (10 accounts, unlimited users) and custom Enterprise pricing. Check the page before you buy, because pricing changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can you use a diagram tool and a pre-deployment review tool together?
&lt;/h3&gt;

&lt;p&gt;Yes. They run at different moments: review the change on the pull request, then refresh documentation diagrams after deploy. The workflow sketch above runs both from one GitHub Actions file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;"Cloud diagram tool" covers at least three jobs: designing, documenting what's live and reviewing a change before it ships. Pick the tool by the question you need answered, and when.&lt;/p&gt;

&lt;p&gt;A diagram of production won't warn you a PR is about to double the bill. A PR gate won't help you whiteboard next quarter.&lt;/p&gt;

&lt;p&gt;If pre-deployment review is the missing piece, read the criterion-by-criterion &lt;a href="https://cloudeval.ai/compare/cloudcraft-alternative?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=diagramming-vs-predeploy&amp;amp;utm_content=cta" rel="noopener noreferrer"&gt;comparison of Cloudcraft and Cloudeval for Azure pre-deployment review&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related on cloudeval.ai&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloudeval.ai/compare?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=diagramming-vs-predeploy&amp;amp;utm_content=related-compare-hub" rel="noopener noreferrer"&gt;Compare Cloudeval with other cloud review and diagram tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloudeval.ai/compare/hava-io-alternative?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=diagramming-vs-predeploy&amp;amp;utm_content=related-hava" rel="noopener noreferrer"&gt;Hava.io alternative for reviewing Azure changes before deployment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloudeval.ai/compare/lucidscale-alternative?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=diagramming-vs-predeploy&amp;amp;utm_content=related-lucid" rel="noopener noreferrer"&gt;Lucid Cloud Accelerator alternative for Azure pre-deployment review&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloudeval.ai/answers/how-to-generate-azure-architecture-diagram?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=diagramming-vs-predeploy&amp;amp;utm_content=related-diagram" rel="noopener noreferrer"&gt;How to generate an Azure architecture diagram automatically&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Try it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Want to see a template as a reviewed diagram before it ships? Open the &lt;a href="https://cloudeval.ai/app?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=diagramming-vs-predeploy&amp;amp;utm_content=try-app" rel="noopener noreferrer"&gt;Cloudeval app&lt;/a&gt; and follow the &lt;a href="https://docs.cloudeval.ai/guides/results/diagrams?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=diagramming-vs-predeploy&amp;amp;utm_content=try-docs" rel="noopener noreferrer"&gt;diagrams and workspace views guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About the author&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prateek Singh&lt;/strong&gt; is the founder of Ganak AI Labs and builds Cloudeval AI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cloudeval.ai/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=diagramming-vs-predeploy&amp;amp;utm_content=author" rel="noopener noreferrer"&gt;cloudeval.ai&lt;/a&gt; | &lt;a href="https://docs.cloudeval.ai/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=diagramming-vs-predeploy&amp;amp;utm_content=author" rel="noopener noreferrer"&gt;Docs&lt;/a&gt; | &lt;a href="https://www.youtube.com/@GanakAILabs" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt; | &lt;a href="https://github.com/ganakailabs" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/prateekkumarsingh/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>cloud</category>
      <category>azure</category>
      <category>devops</category>
      <category>architecture</category>
    </item>
    <item>
      <title>GitHub Actions architecture review gate for Azure pull requests</title>
      <dc:creator>Prateek Singh</dc:creator>
      <pubDate>Tue, 13 Oct 2026 09:30:11 +0000</pubDate>
      <link>https://dev.to/cloudeval-ai/github-actions-architecture-review-gate-for-azure-pull-requests-4f5a</link>
      <guid>https://dev.to/cloudeval-ai/github-actions-architecture-review-gate-for-azure-pull-requests-4f5a</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; An architecture review gate is a GitHub Actions job that checks every pull request against thresholds you set for Well-Architected score, high-risk findings, validation and monthly cost. Run &lt;code&gt;ganakailabs/cloudeval-action&lt;/code&gt; with &lt;code&gt;mode: review&lt;/code&gt;, start with &lt;code&gt;enforcement: comment_only&lt;/code&gt;, then switch to &lt;code&gt;block_pull_request&lt;/code&gt; and make the job a required status check.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;By Prateek Singh, founder of Ganak AI Labs. Updated 13 October 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Your infrastructure pipeline is green. That still doesn't tell you whether the change is a good idea.&lt;/p&gt;

&lt;p&gt;Does it push the bill past budget? Does it open a high-risk exposure? Does it drag the project's Well-Architected score down?&lt;/p&gt;

&lt;p&gt;Usually a busy reviewer answers those questions, if they have time. This guide turns them into a CI step that runs on every pull request, posts one comment and fails when your thresholds aren't met.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I'm the founder of Cloudeval.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The example uses &lt;a href="https://github.com/ganakailabs/cloudeval-action" rel="noopener noreferrer"&gt;&lt;code&gt;ganakailabs/cloudeval-action&lt;/code&gt;&lt;/a&gt;. The rollout pattern (comment first, block later, require the check) works with any review tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  What will you build?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;A linked repository that syncs every pushed commit into a review project.&lt;/li&gt;
&lt;li&gt;A workflow that reviews each pull request and posts one result comment.&lt;/li&gt;
&lt;li&gt;Gates for Well-Architected score, high-risk findings, validation and monthly cost.&lt;/li&gt;
&lt;li&gt;A downloadable review artifact for every run, pass or fail.&lt;/li&gt;
&lt;li&gt;A required status check that blocks merges once you trust the thresholds.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Which terms do you need to know?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Term&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GitHub Actions&lt;/td&gt;
&lt;td&gt;GitHub's built-in CI/CD. A workflow job can run on every pull request.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Required status check&lt;/td&gt;
&lt;td&gt;A branch protection or ruleset setting that blocks a merge until a named job passes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Well-Architected score&lt;/td&gt;
&lt;td&gt;A project score against Azure Well-Architected Framework pillars such as security and reliability.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here's the whole flow in under a minute:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/NCHq0AyEwAo" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  How does an architecture review gate work in GitHub?
&lt;/h2&gt;

&lt;p&gt;Two separate GitHub integrations do the work. Mixing them up is the most common setup mistake.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Piece&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Where it runs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cloudeval GitHub App&lt;/td&gt;
&lt;td&gt;Imports a branch into a project, records the commit SHA and refreshes on push&lt;/td&gt;
&lt;td&gt;Cloudeval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub Action&lt;/td&gt;
&lt;td&gt;Runs the CI review with a scoped access key, applies gates, posts the comment and uploads artifacts&lt;/td&gt;
&lt;td&gt;Your runner&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On each pull request push, the sequence is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The GitHub App syncs the commit.&lt;/li&gt;
&lt;li&gt;The project refreshes its graph, cost, Well-Architected and validation results.&lt;/li&gt;
&lt;li&gt;The workflow runs &lt;code&gt;cloudeval-action&lt;/code&gt; in &lt;code&gt;mode: review&lt;/code&gt; and waits for that commit.&lt;/li&gt;
&lt;li&gt;The gates run, then the action posts the PR comment and uploads artifacts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Coverage is Azure, plus AWS CloudFormation (beta). On Azure it reads ARM JSON (including nested templates through &lt;code&gt;templateLink&lt;/code&gt;) and Bicep compiled to ARM JSON. CloudFormation JSON or YAML is reviewed as a static beta.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; If you write Bicep, commit the compiled &lt;code&gt;main.json&lt;/code&gt; and fail CI when it's stale. The &lt;a href="https://cloudeval.ai/answers/review-bicep-before-deployment?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=gh-actions-review-gate&amp;amp;utm_content=bicep" rel="noopener noreferrer"&gt;Bicep pre-deployment review answer&lt;/a&gt; shows the full pattern.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How do I add an architecture review gate to GitHub pull requests?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Link the repository with the Cloudeval GitHub App.&lt;/li&gt;
&lt;li&gt;Create a project-scoped CI access key and add it as repository secrets.&lt;/li&gt;
&lt;li&gt;Add a workflow that runs &lt;code&gt;ganakailabs/cloudeval-action&lt;/code&gt; in &lt;code&gt;mode: review&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Define gates in &lt;code&gt;.cloudeval/config.yaml&lt;/code&gt;, starting with &lt;code&gt;comment_only&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Read the PR comment and keep the review artifact.&lt;/li&gt;
&lt;li&gt;Switch to &lt;code&gt;block_pull_request&lt;/code&gt; and make the job a required status check.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 1: Link the repository
&lt;/h2&gt;

&lt;p&gt;In Cloudeval, create an Infrastructure-as-code project from GitHub. Install the &lt;a href="https://github.com/apps/cloudeval-ai" rel="noopener noreferrer"&gt;Cloudeval GitHub App&lt;/a&gt; on the repo and pick a branch.&lt;/p&gt;

&lt;p&gt;If your templates live in a subfolder, set a source root such as &lt;code&gt;infra&lt;/code&gt;. Then &lt;code&gt;infra/azuredeploy.json&lt;/code&gt; appears as &lt;code&gt;azuredeploy.json&lt;/code&gt; in the project.&lt;/p&gt;

&lt;p&gt;Put &lt;code&gt;.cloudeval/config.yaml&lt;/code&gt; in the source root. This names the entry template:&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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="na"&gt;stacks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;primary-architecture&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;Primary architecture&lt;/span&gt;
    &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;azuredeploy.json&lt;/span&gt;
    &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;azuredeploy.parameters.json&lt;/span&gt;
&lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;linked_templates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;   &lt;span class="c1"&gt;# follow relative ARM templateLink files&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After import, the project should show the repo, branch, commit SHA and source root. Fix that first if it doesn't.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnd8qrto883vru5x0taz7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnd8qrto883vru5x0taz7.png" alt="Cloudeval project workspace after a GitHub import showing project files, report cards, the code editor, validation counts, cost and Well-Architected status" width="799" height="621"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;After import, files, validation, cost and Well-Architected status share one project.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Create a CI access key and add secrets
&lt;/h2&gt;

&lt;p&gt;In the app, open Developer, then API &amp;amp; CLI access keys. Create a GitHub Actions CI key scoped to that one project. Include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project and report review access (part of the template).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;review:summary&lt;/code&gt;, if you want the AI-written summary in the comment.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;github:comment&lt;/code&gt;, if the comment should come from the Cloudeval GitHub App. Without it, the action falls back to &lt;code&gt;github-actions[bot]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or create one from your terminal and store it in GitHub with this script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cloudeval credentials create &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"GitHub Actions CI - owner/repo"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--template&lt;/span&gt; ci &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CLOUDEVAL_PROJECT_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--expires&lt;/span&gt; 90d &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--show-secret&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--format&lt;/span&gt; json

gh secret &lt;span class="nb"&gt;set &lt;/span&gt;CLOUDEVAL_ACCESS_KEY &lt;span class="nt"&gt;--repo&lt;/span&gt; owner/repo
gh secret &lt;span class="nb"&gt;set &lt;/span&gt;CLOUDEVAL_PROJECT_ID &lt;span class="nt"&gt;--repo&lt;/span&gt; owner/repo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; Run that on your own machine, never in CI logs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Keys expire and aren't renewed in place, so put the expiry date on the team calendar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Add the workflow
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;.github/workflows/cloudeval-review.yml&lt;/code&gt; with this content:&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;Cloudeval review&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;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
  &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;   &lt;span class="c1"&gt;# PR comment&lt;/span&gt;
  &lt;span class="na"&gt;issues&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;          &lt;span class="c1"&gt;# PR lifecycle reactions and the bot-comment fallback&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;review&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;ganakailabs/cloudeval-action@v1&lt;/span&gt;   &lt;span class="c1"&gt;# or pin a full commit SHA&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;access_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.CLOUDEVAL_ACCESS_KEY }}&lt;/span&gt;
          &lt;span class="na"&gt;project_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.CLOUDEVAL_PROJECT_ID }}&lt;/span&gt;
          &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;review&lt;/span&gt;
          &lt;span class="na"&gt;post_pr_comment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;upload_artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Set those three inputs explicitly. By default &lt;code&gt;mode&lt;/code&gt; is &lt;code&gt;ask&lt;/code&gt;, and &lt;code&gt;post_pr_comment&lt;/code&gt; and &lt;code&gt;upload_artifacts&lt;/code&gt; are &lt;code&gt;false&lt;/code&gt;. Leave them out and the workflow runs but gates nothing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The review waits for the GitHub sync of that commit, then writes &lt;code&gt;review.json&lt;/code&gt; and &lt;code&gt;review.md&lt;/code&gt;. It reviews pushed commits only. If an earlier step changes the working tree, it stops with this message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Reviews pushed commits only. Add --ignore-dirty to review HEAD anyway.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So put steps that generate files, like &lt;code&gt;az bicep build&lt;/code&gt;, in a separate job.&lt;/p&gt;

&lt;p&gt;Two optional inputs are worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ai_summary: "false"&lt;/code&gt; gives you gate and report data with no model-written prose.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sarif: true&lt;/code&gt; writes &lt;code&gt;review.sarif.json&lt;/code&gt; from source-mapped findings, ready for GitHub's SARIF upload action.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwawdfpiqxi81vk20d88j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwawdfpiqxi81vk20d88j.png" alt="Expanded AI summary section of a Cloudeval PR comment with top priorities, risks and a recommended next step" width="800" height="757"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The optional AI summary. Turn it off with &lt;code&gt;ai_summary: "false"&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 4: Define the gates, in comment-only mode first
&lt;/h2&gt;

&lt;p&gt;Gates live in &lt;code&gt;.cloudeval/config.yaml&lt;/code&gt; under &lt;code&gt;ci.gates&lt;/code&gt;. Without that block, review mode warns instead of failing, so a fresh setup never blocks anyone by surprise.&lt;/p&gt;

&lt;p&gt;Once the block exists, keys you leave out take defaults: a minimum Well-Architected score of 80, with the high-risk and validation checks on. Set each one on purpose.&lt;/p&gt;

&lt;p&gt;This starter block publishes results without failing anything yet:&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;ci&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;gates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enforcement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;comment_only&lt;/span&gt;          &lt;span class="c1"&gt;# publish results, don't fail the job (yet)&lt;/span&gt;

    &lt;span class="na"&gt;minimum_well_architected_score&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;85&lt;/span&gt; &lt;span class="c1"&gt;# overall, out of 100&lt;/span&gt;
    &lt;span class="na"&gt;minimum_pillar_score&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;           &lt;span class="c1"&gt;# default floor for every pillar&lt;/span&gt;
    &lt;span class="na"&gt;pillars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;security&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;90&lt;/span&gt;
      &lt;span class="na"&gt;reliability&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;85&lt;/span&gt;

    &lt;span class="na"&gt;fail_when_high_risk_findings_exist&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;fail_when_validation_fails&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;   &lt;span class="c1"&gt;# policy checks or unit tests&lt;/span&gt;
    &lt;span class="na"&gt;max_monthly_cost_usd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;500&lt;/span&gt;          &lt;span class="c1"&gt;# omit to report cost without gating it&lt;/span&gt;

  &lt;span class="na"&gt;review&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;outputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;pdf&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;                  &lt;span class="c1"&gt;# attach review/review.pdf to the artifact&lt;/span&gt;
        &lt;span class="na"&gt;report_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;all&lt;/span&gt;
        &lt;span class="na"&gt;verbosity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;evidence&lt;/span&gt;
        &lt;span class="na"&gt;fail_on_error&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Don't copy these numbers blindly. Run a week of PRs in &lt;code&gt;comment_only&lt;/code&gt;, see where your projects score, and set thresholds just below that.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;A gate that fails on day one gets disabled on day two.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Read the PR comment and keep the evidence
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;post_pr_comment: true&lt;/code&gt;, the action reacts when the review starts and finishes. It keeps one result comment per run instead of adding one on every push.&lt;/p&gt;

&lt;p&gt;A typical comment starts like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Overall: PASS
Well-Architected posture: 23.1/100 (critical)
Validation: 3 unit tests failed
Policy checks: good
Cost: 143.81 USD/mo (under 100K budget)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read it as two signals. &lt;code&gt;Overall&lt;/code&gt; is your gate: did the PR meet your thresholds? The posture line is what the review observed.&lt;/p&gt;

&lt;p&gt;A PR can pass a loose gate and still show &lt;code&gt;critical&lt;/code&gt; posture. That isn't a bug. It means your thresholds are looser than your architecture deserves.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frvia6oi10lusz3xf7ukb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frvia6oi10lusz3xf7ukb.png" alt="Cloudeval result comment on a GitHub pull request showing Overall, Well-Architected posture, validation, policy and cost lines" width="800" height="350"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The gate result sits above what the review observed.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Below that sit the source details and expandable sections for pillar scores, cost by service, test failures and the AI summary.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvvdf9eyv6nfipk74w974.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvvdf9eyv6nfipk74w974.png" alt="Expanded PR comment drill-downs with Well-Architected pillar scores and monthly cost by service" width="800" height="951"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Pillar scores and the monthly cost breakdown expand in place.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;upload_artifacts: true&lt;/code&gt;, each run uploads a &lt;code&gt;cloudeval-output&lt;/code&gt; artifact, kept for 14 days by default (&lt;code&gt;artifact_retention_days&lt;/code&gt;). It holds the review JSON, Markdown and, if enabled, PDF.&lt;/p&gt;

&lt;p&gt;It uploads even when the gate fails, which is exactly when you need it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzl9nbnwa4sw82bcujrfy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzl9nbnwa4sw82bcujrfy.png" alt="GitHub Actions run summary for a Cloudeval review job with the review summary and an artifact" width="799" height="406"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The run summary carries the result and a downloadable artifact.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 6: Turn it into a real gate
&lt;/h2&gt;

&lt;p&gt;Once the thresholds stop surprising people:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Change &lt;code&gt;enforcement: comment_only&lt;/code&gt; to &lt;code&gt;enforcement: block_pull_request&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In branch protection or a ruleset, mark the &lt;code&gt;review&lt;/code&gt; job's check as required.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; A workflow can't stop someone clicking Approve. The required status check is what blocks the merge.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Should you use comment_only or block_pull_request?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;comment_only&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;block_pull_request&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Job result when a gate fails&lt;/td&gt;
&lt;td&gt;Passes, results are published&lt;/td&gt;
&lt;td&gt;Fails&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blocks the merge&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes, once the job is a required status check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;The first week, while you calibrate thresholds&lt;/td&gt;
&lt;td&gt;Steady state, once thresholds stop surprising people&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PR comment and artifact&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;
  
  
  Why is my review gate failing?
&lt;/h2&gt;

&lt;p&gt;Match the symptom to the fix:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Likely cause&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;credential_expired&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The access key expired&lt;/td&gt;
&lt;td&gt;Create a new GitHub Actions CI key and replace &lt;code&gt;CLOUDEVAL_ACCESS_KEY&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Missing project" style failure&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;CLOUDEVAL_PROJECT_ID&lt;/code&gt; not set&lt;/td&gt;
&lt;td&gt;Add the secret and pass &lt;code&gt;project_id&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Review can't match repo or ref&lt;/td&gt;
&lt;td&gt;Project not linked to this repo&lt;/td&gt;
&lt;td&gt;Reconnect through GitHub repository sync&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stops with "Reviews pushed commits only"&lt;/td&gt;
&lt;td&gt;An earlier step changed files&lt;/td&gt;
&lt;td&gt;Move generation to another job, or set &lt;code&gt;ignore_dirty: "true"&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comment is from &lt;code&gt;github-actions[bot]&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Key lacks &lt;code&gt;github:comment&lt;/code&gt;, or the project isn't App-linked&lt;/td&gt;
&lt;td&gt;Add the capability or relink&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  What should you check before you enforce the gate?
&lt;/h2&gt;

&lt;p&gt;Copy this checklist into the rollout PR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; [ ] GitHub App installed, project shows repo, branch, commit SHA, source root
&lt;span class="p"&gt;-&lt;/span&gt; [ ] .cloudeval/config.yaml has the correct stack entry (relative to the source root)
&lt;span class="p"&gt;-&lt;/span&gt; [ ] GitHub Actions CI key scoped to one project, expiry on the team calendar
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Workflow sets mode: review, post_pr_comment: true, upload_artifacts: true explicitly
&lt;span class="p"&gt;-&lt;/span&gt; [ ] One week in comment_only, thresholds set from observed scores
&lt;span class="p"&gt;-&lt;/span&gt; [ ] enforcement: block_pull_request and a required status check in branch protection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; PR reviews refresh reports and, by default, generate an AI summary. Both use Cloudeval credits, so budget for them on busy repos.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How do I review infrastructure changes in a GitHub pull request?
&lt;/h3&gt;

&lt;p&gt;Run a review job on the &lt;code&gt;pull_request&lt;/code&gt; event and post the result to the PR. With Cloudeval, the GitHub App syncs the commit, and &lt;code&gt;ganakailabs/cloudeval-action&lt;/code&gt; in &lt;code&gt;mode: review&lt;/code&gt; applies your gates and posts one result comment.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I make a GitHub Actions job block a merge?
&lt;/h3&gt;

&lt;p&gt;Make the job fail when the gate isn't met (&lt;code&gt;enforcement: block_pull_request&lt;/code&gt;), then mark it as a required status check in branch protection or a ruleset.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does the review gate work with Bicep?
&lt;/h3&gt;

&lt;p&gt;Yes, through compiled ARM JSON. Commit the &lt;code&gt;main.json&lt;/code&gt; that &lt;code&gt;az bicep build&lt;/code&gt; produces and fail CI when it's stale. Cloudeval doesn't parse &lt;code&gt;.bicep&lt;/code&gt; files directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is the PR comment posted by github-actions[bot]?
&lt;/h3&gt;

&lt;p&gt;The comment uses the Cloudeval GitHub App identity only when the project is linked to the same repo, the key has &lt;code&gt;github:comment&lt;/code&gt;, and the job has &lt;code&gt;pull-requests: write&lt;/code&gt; and &lt;code&gt;issues: write&lt;/code&gt;. Otherwise it falls back to &lt;code&gt;github-actions[bot]&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does it comment on pull requests from forks?
&lt;/h3&gt;

&lt;p&gt;Often not. GitHub usually gives fork PRs a read-only workflow token, so the comment is skipped. That's GitHub's restriction, not the action's.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the takeaway?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A review gate is a policy decision more than a tooling one.&lt;/strong&gt; Decide what "safe to merge" means, write it down as thresholds, and publish results before you enforce them.&lt;/p&gt;

&lt;p&gt;Want to see it first? The &lt;a href="https://github.com/ganakailabs/cloudeval-azure-arm-review-example" rel="noopener noreferrer"&gt;public Azure ARM review example&lt;/a&gt; has demo PRs that pass, fail on cost and fail on risk.&lt;/p&gt;

&lt;p&gt;For the overview, read &lt;a href="https://cloudeval.ai/solutions/github-cloud-review?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=gh-actions-review-gate&amp;amp;utm_content=cta" rel="noopener noreferrer"&gt;Cloud infrastructure review in GitHub pull requests&lt;/a&gt;. The full input reference is in the &lt;a href="https://docs.cloudeval.ai/guides/review/github-actions?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=gh-actions-review-gate&amp;amp;utm_content=docs" rel="noopener noreferrer"&gt;GitHub Actions guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related on cloudeval.ai&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloudeval.ai/solutions/github-cloud-review?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=gh-actions-review-gate&amp;amp;utm_content=related-solution" rel="noopener noreferrer"&gt;Cloud infrastructure review in GitHub pull requests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloudeval.ai/answers/review-bicep-before-deployment?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=gh-actions-review-gate&amp;amp;utm_content=related-bicep" rel="noopener noreferrer"&gt;How to review a Bicep or ARM template before deployment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloudeval.ai/glossary/iac-review?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=gh-actions-review-gate&amp;amp;utm_content=related-glossary" rel="noopener noreferrer"&gt;What is IaC review?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloudeval.ai/guides/connect/github-repository?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=gh-actions-review-gate&amp;amp;utm_content=related-sync-docs" rel="noopener noreferrer"&gt;GitHub repository sync docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Next step:&lt;/strong&gt; Ready to gate your own pull requests? Open the &lt;a href="https://cloudeval.ai/app?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=gh-actions-review-gate&amp;amp;utm_content=try-app" rel="noopener noreferrer"&gt;Cloudeval app&lt;/a&gt; and follow the &lt;a href="https://docs.cloudeval.ai/guides/review/github-actions?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=gh-actions-review-gate&amp;amp;utm_content=try-docs" rel="noopener noreferrer"&gt;GitHub Actions guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About the author&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prateek Singh&lt;/strong&gt; is the founder of Ganak AI Labs and builds Cloudeval AI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cloudeval.ai/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=gh-actions-review-gate&amp;amp;utm_content=author" rel="noopener noreferrer"&gt;cloudeval.ai&lt;/a&gt; | &lt;a href="https://docs.cloudeval.ai/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=gh-actions-review-gate&amp;amp;utm_content=author" rel="noopener noreferrer"&gt;Docs&lt;/a&gt; | &lt;a href="https://www.youtube.com/@GanakAILabs" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt; | &lt;a href="https://github.com/ganakailabs" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/prateekkumarsingh/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>githubactions</category>
      <category>github</category>
      <category>azure</category>
      <category>devops</category>
    </item>
    <item>
      <title>Review Bicep before deployment: what-if, linter and cost</title>
      <dc:creator>Prateek Singh</dc:creator>
      <pubDate>Tue, 06 Oct 2026 09:30:35 +0000</pubDate>
      <link>https://dev.to/cloudeval-ai/review-bicep-before-deployment-what-if-linter-and-cost-4pcf</link>
      <guid>https://dev.to/cloudeval-ai/review-bicep-before-deployment-what-if-linter-and-cost-4pcf</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; To review a Bicep change before deployment, compile it with &lt;code&gt;az bicep build&lt;/code&gt;, run the Bicep linter, &lt;code&gt;az deployment group validate&lt;/code&gt; and what-if, then review the compiled ARM JSON for design, cost and security. what-if shows what will change in Azure. It doesn't tell you whether the change is safe, affordable or exposed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;By Prateek Singh, founder of Ganak AI Labs. Updated 6 October 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Your pull request touches &lt;code&gt;main.bicep&lt;/code&gt;. CI is green, and what-if prints a tidy list of &lt;code&gt;+ Create&lt;/code&gt; and &lt;code&gt;~ Modify&lt;/code&gt; lines. Someone approves it.&lt;/p&gt;

&lt;p&gt;Two weeks later you learn the "small" change opened a storage account to the internet, or doubled the bill with a new SKU.&lt;/p&gt;

&lt;p&gt;None of the tools lied. what-if tells you what will change, not whether it's safe. Here's how to answer that second question in the same PR, plus a checklist to copy.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I'm the founder of Cloudeval.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key terms used below&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bicep:&lt;/strong&gt; Microsoft's language for Azure infrastructure. It compiles to an ARM template.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ARM template:&lt;/strong&gt; the Azure Resource Manager JSON file that Azure actually deploys.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;what-if:&lt;/strong&gt; an Azure CLI command that previews changes against what's already deployed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bicep linter:&lt;/strong&gt; the built-in checker, configured in &lt;code&gt;bicepconfig.json&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What does each Bicep pre-deployment check catch?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Catches&lt;/th&gt;
&lt;th&gt;Needs Azure access?&lt;/th&gt;
&lt;th&gt;Misses&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;az bicep build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Syntax and type errors&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Intent and design&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bicep linter&lt;/td&gt;
&lt;td&gt;Hard-coded URLs, secrets in outputs, insecure defaults, old API versions&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Topology, cost, cross-resource risk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;az deployment group validate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Whether Resource Manager accepts the template at a real scope&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Whether you should deploy it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;what-if&lt;/td&gt;
&lt;td&gt;The resource-level diff against current Azure state&lt;/td&gt;
&lt;td&gt;Yes, deploy-level&lt;/td&gt;
&lt;td&gt;Whether that diff is safe or affordable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Design, cost and security review&lt;/td&gt;
&lt;td&gt;Public exposure, dependency shape, cost drivers&lt;/td&gt;
&lt;td&gt;Not for template review&lt;/td&gt;
&lt;td&gt;Runtime behaviour, live drift&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Keep the first four. The gap is the last row.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I review a Bicep change before deployment?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Compile the Bicep file to ARM JSON with &lt;code&gt;az bicep build&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run the native checks: the linter, &lt;code&gt;validate&lt;/code&gt; and what-if.&lt;/li&gt;
&lt;li&gt;Review design, cost and security on the compiled ARM JSON, locally or on every pull request.&lt;/li&gt;
&lt;li&gt;Read the findings in a fixed order, then re-run what-if right before you deploy.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 1: Compile with &lt;code&gt;az bicep build&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Bicep compiles to ARM JSON, and that's what Azure actually deploys.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az bicep build &lt;span class="nt"&gt;--file&lt;/span&gt; ./infra/main.bicep &lt;span class="nt"&gt;--outfile&lt;/span&gt; ./infra/main.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compile a &lt;code&gt;.bicepparam&lt;/code&gt; file the same way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az bicep build-params &lt;span class="nt"&gt;--file&lt;/span&gt; ./infra/main.bicepparam &lt;span class="nt"&gt;--outfile&lt;/span&gt; ./infra/main.parameters.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make this your first CI step. Skim the JSON on module changes too. A one-line version bump can change many resources, and only the compiled output shows it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Run the native checks (linter, validate, what-if)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The linter
&lt;/h3&gt;

&lt;p&gt;Set the rules that matter for review to &lt;code&gt;error&lt;/code&gt; in &lt;code&gt;bicepconfig.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"analyzers"&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="nl"&gt;"core"&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="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"rules"&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="nl"&gt;"outputs-should-not-contain-secrets"&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="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&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="nl"&gt;"secure-parameter-default"&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="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&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="nl"&gt;"use-secure-value-for-secure-inputs"&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="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&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="nl"&gt;"no-hardcoded-environment-urls"&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="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&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="nl"&gt;"use-recent-api-versions"&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="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"warning"&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="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="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run it in CI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az bicep lint &lt;span class="nt"&gt;--file&lt;/span&gt; ./infra/main.bicep
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  validate and what-if
&lt;/h3&gt;

&lt;p&gt;These two need a real Azure scope:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az deployment group validate &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--resource-group&lt;/span&gt; rg-app-dev &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--template-file&lt;/span&gt; ./infra/main.bicep &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--parameters&lt;/span&gt; ./infra/main.bicepparam

az deployment group what-if &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--resource-group&lt;/span&gt; rg-app-dev &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--template-file&lt;/span&gt; ./infra/main.bicep &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--parameters&lt;/span&gt; ./infra/main.bicepparam
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;sub&lt;/code&gt;, &lt;code&gt;mg&lt;/code&gt; and &lt;code&gt;tenant&lt;/code&gt; variants cover other scopes. Keep in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what-if needs deploy permissions, including &lt;code&gt;Microsoft.Resources/deployments/*&lt;/code&gt;. Reviewers often lack them.&lt;/li&gt;
&lt;li&gt;Azure-set defaults can show up as changes that won't happen.&lt;/li&gt;
&lt;li&gt;Resources deployed through &lt;code&gt;templateLink&lt;/code&gt;, including template specs, aren't expanded.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For refactors, &lt;code&gt;bicep snapshot&lt;/code&gt; (Bicep CLI 0.41.2+) diffs what a &lt;code&gt;.bicepparam&lt;/code&gt; would deploy, without contacting Azure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bicep snapshot &lt;span class="nt"&gt;--mode&lt;/span&gt; overwrite ./infra/main.bicepparam   &lt;span class="c"&gt;# on main&lt;/span&gt;
bicep snapshot &lt;span class="nt"&gt;--mode&lt;/span&gt; validate  ./infra/main.bicepparam   &lt;span class="c"&gt;# on the PR branch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You now know what will change. You still don't know if it's a good idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Review design, cost and security
&lt;/h2&gt;

&lt;p&gt;Most pipelines skip this layer because it meant reading raw JSON by hand. Use any tool your team trusts. PSRule for Azure is a solid open-source option.&lt;/p&gt;

&lt;p&gt;I'll use &lt;a href="https://cloudeval.ai/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=review-bicep-tutorial&amp;amp;utm_content=step3" rel="noopener noreferrer"&gt;Cloudeval&lt;/a&gt; here. It reviews the compiled ARM JSON and returns architecture and dependency diagrams with cost and security findings. It doesn't read &lt;code&gt;.bicep&lt;/code&gt; files directly, which is why Step 1 matters.&lt;/p&gt;

&lt;p&gt;Here's a two-minute demo:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Xzt4cNKUHxU" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Option A: from your terminal
&lt;/h3&gt;

&lt;p&gt;Install and sign in:&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; @ganakailabs/cloudeval-cli   &lt;span class="c"&gt;# Node.js 20+&lt;/span&gt;
cloudeval login            &lt;span class="c"&gt;# or: cloudeval login --headless  (SSH/containers)&lt;/span&gt;
cloudeval auth status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a project from the compiled template and run every report:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cloudeval projects create &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--template-file&lt;/span&gt; ./infra/main.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--parameters-file&lt;/span&gt; ./infra/main.parameters.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"PR 1234 - main.bicep"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--provider&lt;/span&gt; azure &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--format&lt;/span&gt; json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; ./cloudeval-project.json

&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.data.project.id'&lt;/span&gt; ./cloudeval-project.json&lt;span class="si"&gt;)&lt;/span&gt;

cloudeval reports run &lt;span class="nt"&gt;--project&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; all &lt;span class="nt"&gt;--wait&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs against the template, not your subscription, so you need a Cloudeval account but no Azure credentials.&lt;/p&gt;

&lt;p&gt;Read the results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cloudeval reports waf  &lt;span class="nt"&gt;--project&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; markdown   &lt;span class="c"&gt;# architecture findings&lt;/span&gt;
cloudeval reports cost &lt;span class="nt"&gt;--project&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; markdown   &lt;span class="c"&gt;# cost estimate&lt;/span&gt;

cloudeval issues list &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--type&lt;/span&gt; architecture,cost &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--severity&lt;/span&gt; critical,high &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--format&lt;/span&gt; json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbv3amsjw3j9sq2v65blt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbv3amsjw3j9sq2v65blt.png" alt="Cloudeval Top Actions list with findings such as Azure.Storage.BlobPublicAccess and Azure.Storage.Firewall, each tagged Security, Cost or Operational" width="800" height="795"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Each finding names the rule, the resource type and the pillar.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Or open the diagram:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cloudeval open project &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--view&lt;/span&gt; preview &lt;span class="nt"&gt;--layout&lt;/span&gt; dependency &lt;span class="nt"&gt;--print-url&lt;/span&gt; &lt;span class="nt"&gt;--no-open&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuuv3x8vp5wcqv7y740oy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuuv3x8vp5wcqv7y740oy.png" alt="Cloudeval split view with the generated architecture diagram on the left and the project file explorer and ARM JSON outline on the right" width="799" height="419"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The generated diagram sits next to your files and ARM JSON outline.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Prefer clicking? In the web app, choose Projects, then Create project, then Upload Template File, and drop in &lt;code&gt;main.json&lt;/code&gt; (up to 2 MB). The &lt;a href="https://docs.cloudeval.ai/guides/connect/arm-bicep?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=review-bicep-tutorial&amp;amp;utm_content=import-docs" rel="noopener noreferrer"&gt;import guide&lt;/a&gt; covers URLs, parameter files and linked templates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fukc8tgeqge0qt7a36kzb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fukc8tgeqge0qt7a36kzb.png" alt="Imported ARM template beside project files and the generated ARM JSON outline in Cloudeval" width="800" height="393"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Your template, ARM JSON outline and report history live in one workspace.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Option B: on every pull request (GitHub Action)
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ganakailabs/cloudeval-action&lt;/code&gt; posts one result comment per PR run. It can also write SARIF output and enforce merge gates.&lt;/p&gt;

&lt;p&gt;Setup takes three steps (see the &lt;a href="https://docs.cloudeval.ai/guides/review/github-actions?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=review-bicep-tutorial&amp;amp;utm_content=action-docs" rel="noopener noreferrer"&gt;GitHub Actions guide&lt;/a&gt;):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Link the repo to a Cloudeval project with the Cloudeval GitHub App.&lt;/li&gt;
&lt;li&gt;Create a CI access key scoped to that project.&lt;/li&gt;
&lt;li&gt;Add the &lt;code&gt;CLOUDEVAL_ACCESS_KEY&lt;/code&gt; and &lt;code&gt;CLOUDEVAL_PROJECT_ID&lt;/code&gt; repository secrets.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One Bicep detail: the action reviews the synced files at the pushed commit, and it reads ARM JSON. So commit the compiled &lt;code&gt;infra/main.json&lt;/code&gt; and &lt;code&gt;main.parameters.json&lt;/code&gt;, and fail CI if they're stale.&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;Bicep review&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;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
  &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
  &lt;span class="na"&gt;issues&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&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;native-checks&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;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;az bicep lint --file ./infra/main.bicep&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;Compiled ARM JSON must be up to date&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;az bicep build --file ./infra/main.bicep --outfile ./infra/main.json&lt;/span&gt;
          &lt;span class="s"&gt;git diff --exit-code -- ./infra/main.json&lt;/span&gt;

  &lt;span class="na"&gt;cloudeval-review&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;ganakailabs/cloudeval-action@v1&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;access_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.CLOUDEVAL_ACCESS_KEY }}&lt;/span&gt;
          &lt;span class="na"&gt;project_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.CLOUDEVAL_PROJECT_ID }}&lt;/span&gt;
          &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;review&lt;/span&gt;
          &lt;span class="na"&gt;post_pr_comment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;upload_artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep the jobs separate. The review job stops on a dirty working tree, and building inside it would dirty it.&lt;/p&gt;

&lt;p&gt;Set the entry point and gates in &lt;code&gt;.cloudeval/config.yaml&lt;/code&gt; at the root of the synced source. With a source root of &lt;code&gt;infra&lt;/code&gt;, that's &lt;code&gt;infra/.cloudeval/config.yaml&lt;/code&gt;:&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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="na"&gt;stacks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
    &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;main.json&lt;/span&gt;                   &lt;span class="c1"&gt;# relative to the source root: infra/main.json -&amp;gt; main.json&lt;/span&gt;
    &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;main.parameters.json&lt;/span&gt;
&lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;linked_templates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;ci&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;gates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enforcement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;comment_only&lt;/span&gt;   &lt;span class="c1"&gt;# switch to block_pull_request once thresholds are tuned&lt;/span&gt;
    &lt;span class="na"&gt;minimum_well_architected_score&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;   &lt;span class="c1"&gt;# the default once ci.gates exists; set your own floor&lt;/span&gt;
    &lt;span class="na"&gt;fail_when_high_risk_findings_exist&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;fail_when_validation_fails&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;max_monthly_cost_usd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;500&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keys you leave out of &lt;code&gt;ci.gates&lt;/code&gt; take defaults, so set the score floor on purpose. Start with &lt;code&gt;comment_only&lt;/code&gt;. Once you trust the thresholds, switch to &lt;code&gt;block_pull_request&lt;/code&gt; and make the job a required status check.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Read the findings
&lt;/h2&gt;

&lt;p&gt;The PR comment keeps your gate separate from what the review saw:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Overall: PASS
Well-Architected posture: 23.1/100 (critical)
Validation: 3 unit tests failed
Policy checks: good
Cost: 143.81 USD/mo (under 100K budget)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Overall&lt;/code&gt; reflects your thresholds. &lt;code&gt;critical&lt;/code&gt; is the posture Cloudeval observed. A PR can pass a loose gate and still deserve a hard look.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9o8aqxvic7ty48qmgh0n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9o8aqxvic7ty48qmgh0n.png" alt="Expanded Cloudeval PR comment showing validation details (unit tests and policy checks) and architecture signals such as resource count, relationships and high-risk findings" width="800" height="272"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The expanded comment shows validation results and architecture signals.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Read the findings in this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Dependency view. Does the topology match the PR description? Look for surprise public endpoints, identity or subnet changes.&lt;/li&gt;
&lt;li&gt;High-severity findings. Did this PR change the affected resource?&lt;/li&gt;
&lt;li&gt;Cost drivers. Should a SKU change before rollout? Numbers are estimates.&lt;/li&gt;
&lt;li&gt;Gaps. "Not assessed" doesn't mean safe.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frjgfoq8fo1azkrnooh5p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frjgfoq8fo1azkrnooh5p.png" alt="Cloudeval dependency view of an Azure template with one resource selected and its upstream and downstream paths highlighted" width="800" height="603"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Select a resource to see its upstream and downstream paths.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then run what-if at deploy time anyway.&lt;/p&gt;

&lt;h2&gt;
  
  
  What belongs in a Bicep pre-deploy checklist?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Bicep pre-deploy review&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; [ ] &lt;span class="sb"&gt;`az bicep build`&lt;/span&gt; passes, compiled ARM JSON is committed and up to date
&lt;span class="p"&gt;-&lt;/span&gt; [ ] &lt;span class="sb"&gt;`az bicep lint`&lt;/span&gt; clean (security-relevant rules set to &lt;span class="sb"&gt;`error`&lt;/span&gt;)
&lt;span class="p"&gt;-&lt;/span&gt; [ ] &lt;span class="sb"&gt;`az deployment group validate`&lt;/span&gt; passes at the target scope
&lt;span class="p"&gt;-&lt;/span&gt; [ ] &lt;span class="sb"&gt;`what-if`&lt;/span&gt; diff matches the PR description (no surprise Delete/Modify)
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Linked/nested templates and template specs reviewed separately (what-if doesn't expand templateLink)
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Dependency diagram reviewed: no unintended public exposure, identity or subnet changes
&lt;span class="p"&gt;-&lt;/span&gt; [ ] High/critical findings triaged: fixed, waived with reason, or ticketed
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Monthly cost estimate checked against budget, SKU choices justified
&lt;span class="p"&gt;-&lt;/span&gt; [ ] "Not assessed" areas noted, not assumed safe
&lt;span class="p"&gt;-&lt;/span&gt; [ ] what-if re-run immediately before the real deployment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What doesn't a template review catch?
&lt;/h2&gt;

&lt;p&gt;Cloudeval adds diagrams, cost and security findings from 1,650+ checks, right in the PR. It covers Azure, plus AWS CloudFormation (beta).&lt;/p&gt;

&lt;p&gt;It can't prove runtime behaviour, and it doesn't replace what-if, the only real answer to "what changes in this subscription right now". It doesn't catch live drift yet either. Drift comparison is planned, and live Azure state comes in through a separate Cloud sync.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How do I preview Azure deployment changes before deploying?
&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;az deployment group what-if&lt;/code&gt; with the template and parameters you'll deploy. It lists each resource that would be created, modified or deleted, and needs deploy permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does Bicep what-if show changes that won't happen?
&lt;/h3&gt;

&lt;p&gt;Properties Azure sets as defaults can show up as changes even though nothing will change. Check unexpected Delete or Modify lines against the PR description first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I review a Bicep change without access to the Azure subscription?
&lt;/h3&gt;

&lt;p&gt;Partly. &lt;code&gt;build&lt;/code&gt;, the linter and &lt;code&gt;bicep snapshot&lt;/code&gt; run locally, but &lt;code&gt;validate&lt;/code&gt; and what-if need deploy-level access. Cloudeval works from the compiled ARM JSON, so you need a Cloudeval account, not subscription credentials.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does Cloudeval read &lt;code&gt;.bicep&lt;/code&gt; files directly?
&lt;/h3&gt;

&lt;p&gt;No. Compile with &lt;code&gt;az bicep build&lt;/code&gt; and review the ARM JSON. That's what Azure actually deploys anyway.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I block a merge on high-risk findings or cost?
&lt;/h3&gt;

&lt;p&gt;Add &lt;code&gt;ci.gates&lt;/code&gt; to &lt;code&gt;.cloudeval/config.yaml&lt;/code&gt;, for example &lt;code&gt;fail_when_high_risk_findings_exist&lt;/code&gt; or &lt;code&gt;max_monthly_cost_usd&lt;/code&gt;. Set &lt;code&gt;enforcement: block_pull_request&lt;/code&gt; and make the job a required check in branch protection.&lt;/p&gt;




&lt;p&gt;For the longer version, read &lt;a href="https://cloudeval.ai/answers/review-bicep-before-deployment?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=review-bicep-tutorial&amp;amp;utm_content=cta" rel="noopener noreferrer"&gt;How do I review a Bicep or ARM template before deployment?&lt;/a&gt; Or browse a &lt;a href="https://github.com/ganakailabs/cloudeval-azure-arm-review-example/pull/8" rel="noopener noreferrer"&gt;public example PR&lt;/a&gt; with real caveats, including failed validation tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related on cloudeval.ai&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloudeval.ai/answers/bicep-to-cloud-diagram?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=review-bicep-tutorial&amp;amp;utm_content=related-diagram" rel="noopener noreferrer"&gt;How to convert Bicep to a cloud architecture diagram&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloudeval.ai/solutions/github-cloud-review?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=review-bicep-tutorial&amp;amp;utm_content=related-github" rel="noopener noreferrer"&gt;Cloud infrastructure review in GitHub pull requests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloudeval.ai/glossary/iac-review?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=review-bicep-tutorial&amp;amp;utm_content=related-glossary" rel="noopener noreferrer"&gt;What is IaC review?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloudeval.ai/compare?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=review-bicep-tutorial&amp;amp;utm_content=related-compare" rel="noopener noreferrer"&gt;Compare Cloudeval with other cloud review and diagram tools&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Try it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Compile your Bicep, then review the ARM JSON before it ships. Open the &lt;a href="https://cloudeval.ai/app?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=review-bicep-tutorial&amp;amp;utm_content=try-app" rel="noopener noreferrer"&gt;Cloudeval app&lt;/a&gt; and follow the &lt;a href="https://docs.cloudeval.ai/guides/review/iac-before-deployment?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=review-bicep-tutorial&amp;amp;utm_content=try-docs" rel="noopener noreferrer"&gt;IaC pre-deployment review guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About the author&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prateek Singh&lt;/strong&gt; is the founder of Ganak AI Labs and builds Cloudeval AI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cloudeval.ai/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=review-bicep-tutorial&amp;amp;utm_content=author" rel="noopener noreferrer"&gt;cloudeval.ai&lt;/a&gt; | &lt;a href="https://docs.cloudeval.ai/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=review-bicep-tutorial&amp;amp;utm_content=author" rel="noopener noreferrer"&gt;Docs&lt;/a&gt; | &lt;a href="https://www.youtube.com/@GanakAILabs" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt; | &lt;a href="https://github.com/ganakailabs" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/prateekkumarsingh/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>azure</category>
      <category>bicep</category>
      <category>devops</category>
      <category>infrastructureascode</category>
    </item>
    <item>
      <title>Give Cursor, Claude Code or Codex your Azure architecture over MCP</title>
      <dc:creator>Prateek Singh</dc:creator>
      <pubDate>Fri, 02 Oct 2026 08:00:33 +0000</pubDate>
      <link>https://dev.to/cloudeval-ai/give-cursor-claude-code-or-codex-your-azure-architecture-over-mcp-1b31</link>
      <guid>https://dev.to/cloudeval-ai/give-cursor-claude-code-or-codex-your-azure-architecture-over-mcp-1b31</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; To give Cursor, Claude Code or Codex your Azure architecture, run the Cloudeval CLI's local MCP server (&lt;code&gt;npx -y @ganakailabs/cloudeval-cli mcp serve --toolset readonly&lt;/code&gt;) with a project-scoped, read-only access key. The agent can then read your architecture graph and saved cost and Well-Architected reports. It can't deploy or change Azure resources.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;By Prateek Singh, founder of Ganak AI Labs, the team behind Cloudeval AI. Published 2 October 2026; commands checked against @ganakailabs/cloudeval-cli 0.38.5 and each client's MCP docs that day.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ask a coding agent "is this storage account reachable from the internet?" and it will happily read &lt;code&gt;main.bicep&lt;/code&gt; and give you an answer. What it can't see is everything outside the file: the other resource groups, the subnet the private endpoint lands in, the cost report from last week, the Well-Architected findings nobody has triaged yet. So it guesses, confidently.&lt;/p&gt;

&lt;p&gt;The Model Context Protocol (MCP) fixes the plumbing side of this. Instead of you pasting screenshots and JSON into chat, the agent calls a tool server and gets structured answers back. This post shows how to connect Cursor, Claude Code or Codex to an MCP server that exposes your Azure architecture graph and saved reports, with a read-only toolset and a scoped key. It finishes with prompts that actually produce useful answers.&lt;/p&gt;

&lt;p&gt;This isn't Microsoft's Azure MCP Server, which queries live Azure resources. The two can run side by side.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key terms used below&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MCP (Model Context Protocol):&lt;/strong&gt; an open protocol that lets AI clients such as Cursor, Claude Code and Codex call external tool servers and get structured results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;stdio server:&lt;/strong&gt; an MCP server the client starts as a local process. It has no network endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ARM / Bicep:&lt;/strong&gt; Azure Resource Manager JSON templates, and Microsoft's Bicep language that compiles to them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The server I'm using is the one in the &lt;a href="https://cloudeval.ai/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=mcp-azure-review&amp;amp;utm_content=intro" rel="noopener noreferrer"&gt;Cloudeval&lt;/a&gt; CLI, because it's the one I know best.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I'm the founder of Cloudeval (Ganak AI Labs).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you prefer to watch first, here is the 52-second version of the idea: the same review context, reachable from the terminal, the IDE, CI and your own agents.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/wA6poXNBlVs" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What can a coding agent read over MCP, and what can't it do?
&lt;/h2&gt;

&lt;p&gt;Before wiring anything up, it's worth being precise about the boundary.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;The agent &lt;strong&gt;can&lt;/strong&gt; read (default &lt;code&gt;readonly&lt;/code&gt; toolset)&lt;/th&gt;
&lt;th&gt;The agent &lt;strong&gt;can't&lt;/strong&gt; do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Projects your key can see, plus details and overview&lt;/td&gt;
&lt;td&gt;Deploy, change or remediate Azure resources&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Architecture graph nodes and relationships&lt;/td&gt;
&lt;td&gt;See anything outside the projects the key is scoped to&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Saved cost and Well-Architected reports and rule results&lt;/td&gt;
&lt;td&gt;Run reports or AI answers (those need an explicit, wider toolset)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The validation check catalogue&lt;/td&gt;
&lt;td&gt;Reach a hosted endpoint: the server runs locally over &lt;strong&gt;stdio&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent Profile definitions (&lt;code&gt;architecture&lt;/code&gt;, &lt;code&gt;cost&lt;/code&gt;, &lt;code&gt;security-reviewer&lt;/code&gt;, ...)&lt;/td&gt;
&lt;td&gt;Read live AWS or GCP. Inputs are live Azure (Cloud sync), ARM JSON, Bicep compiled to ARM, and AWS CloudFormation as a static beta&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The data comes from Cloudeval projects, so you need at least one: either a live Azure subscription connected through Cloud sync, or an imported template. If you write Bicep, compile it first (&lt;code&gt;az bicep build&lt;/code&gt;) and import the ARM JSON. Cloudeval reviews the compiled output rather than parsing &lt;code&gt;.bicep&lt;/code&gt; directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I connect Cursor, Claude Code or Codex to Azure architecture over MCP?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create a scoped, read-only access key.&lt;/li&gt;
&lt;li&gt;Check the server locally with &lt;code&gt;mcp status&lt;/code&gt; and &lt;code&gt;doctor --mcp&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add the stdio server to your client's MCP config.&lt;/li&gt;
&lt;li&gt;Verify the tool list and the project scope.&lt;/li&gt;
&lt;li&gt;Keep the &lt;code&gt;readonly&lt;/code&gt; toolset and widen access only on purpose.&lt;/li&gt;
&lt;li&gt;Use Agent Profiles as reviewer lenses.&lt;/li&gt;
&lt;li&gt;Use prompts that ask for cited evidence.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each step is covered below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create a scoped, read-only access key
&lt;/h2&gt;

&lt;p&gt;Don't hand an agent your interactive login. Create a dedicated key:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Cloudeval app, open &lt;strong&gt;Developer → API &amp;amp; CLI access keys&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Create a key from the &lt;strong&gt;MCP Read-only&lt;/strong&gt; template.&lt;/li&gt;
&lt;li&gt;Scope it to the one project you want the agent to see.&lt;/li&gt;
&lt;li&gt;Check the expiry and capabilities. The template defaults to 30 days. It includes project, connection, report, download, diagram-export and MCP access, but &lt;strong&gt;not&lt;/strong&gt; billing reads or evaluation runs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqmf3ybvy3gbn434n8duj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqmf3ybvy3gbn434n8duj.png" alt="Cloudeval create auth key form with the MCP Read-only template selected, a project scope picker and a 30d expiry" width="800" height="377"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The create-key form with the MCP Read-only template, a project scope and the 30-day default expiry (the docs example names the key for another client; name yours after the agent that uses it). (Source: Cloudeval docs)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Store it in your shell profile or secret manager as &lt;code&gt;CLOUDEVAL_ACCESS_KEY&lt;/code&gt;. Each client config below reads it from the environment, so the secret never lands in a file you might commit.&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;export &lt;/span&gt;&lt;span class="nv"&gt;CLOUDEVAL_ACCESS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;your scoped key&amp;gt;"&lt;/span&gt;   &lt;span class="c"&gt;# keep out of dotfiles you commit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Check the server locally
&lt;/h2&gt;

&lt;p&gt;You need Node.js 20+. The no-install form uses &lt;code&gt;npx&lt;/code&gt;. If you'd rather install globally, run &lt;code&gt;npm install -g @ganakailabs/cloudeval-cli&lt;/code&gt; and use &lt;code&gt;cloudeval&lt;/code&gt; 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;# Inspect the MCP surface and diagnose local setup before touching any client&lt;/span&gt;
npx &lt;span class="nt"&gt;-y&lt;/span&gt; @ganakailabs/cloudeval-cli mcp status &lt;span class="nt"&gt;--format&lt;/span&gt; json
npx &lt;span class="nt"&gt;-y&lt;/span&gt; @ganakailabs/cloudeval-cli doctor &lt;span class="nt"&gt;--mcp&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F25e9tyqv4nabepqjg9u2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F25e9tyqv4nabepqjg9u2.png" alt="Terminal output of cloudeval doctor --mcp --format json listing the MCP server info, toolsets, tools, resources and prompts" width="799" height="544"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;code&gt;doctor --mcp --format json&lt;/code&gt; shows the server, toolsets, tools, resources and prompts before any client is involved (docs capture from an earlier CLI version, so your lists may be longer). (Source: Cloudeval docs)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The command every client will launch is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; @ganakailabs/cloudeval-cli mcp serve &lt;span class="nt"&gt;--toolset&lt;/span&gt; &lt;span class="nb"&gt;readonly&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things that trip people up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don't run &lt;code&gt;login&lt;/code&gt; through the MCP process.&lt;/strong&gt; &lt;code&gt;mcp serve&lt;/code&gt; reserves stdin for protocol messages. Authenticate beforehand (stored &lt;code&gt;cloudeval login&lt;/code&gt;, or &lt;code&gt;cloudeval login --headless&lt;/code&gt; over SSH), or rely on the env var.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Containers don't inherit your host login.&lt;/strong&gt; Pass the scoped key at runtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The CLI can also generate the config for you. Always start with &lt;code&gt;--dry-run&lt;/code&gt; so you can read what it would write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cloudeval mcp setup cursor &lt;span class="nt"&gt;--dry-run&lt;/span&gt; &lt;span class="nt"&gt;--toolset&lt;/span&gt; &lt;span class="nb"&gt;readonly
&lt;/span&gt;cloudeval mcp setup codex  &lt;span class="nt"&gt;--dry-run&lt;/span&gt; &lt;span class="nt"&gt;--toolset&lt;/span&gt; &lt;span class="nb"&gt;readonly
&lt;/span&gt;cloudeval mcp setup claude &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
cloudeval mcp setup generic &lt;span class="nt"&gt;--dry-run&lt;/span&gt; &lt;span class="nt"&gt;--toolset&lt;/span&gt; &lt;span class="nb"&gt;readonly&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The supported targets are &lt;code&gt;codex&lt;/code&gt;, &lt;code&gt;claude&lt;/code&gt;, &lt;code&gt;cursor&lt;/code&gt;, &lt;code&gt;vscode&lt;/code&gt; and &lt;code&gt;generic&lt;/code&gt;. &lt;code&gt;--toolset&lt;/code&gt; defaults to &lt;code&gt;readonly&lt;/code&gt;. Without &lt;code&gt;--dry-run&lt;/code&gt;, setup can write to the client's config file. Pass &lt;code&gt;--config-path&lt;/code&gt; if you want to control where it goes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Wire up your client
&lt;/h2&gt;

&lt;p&gt;Every client below runs the same stdio command. Only the config syntax differs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3vmpcuushw0nwf6ffni0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3vmpcuushw0nwf6ffni0.png" alt="Cloudeval MCP client configs for Codex, Cursor, Claude Code, VS Code and generic clients" width="800" height="597"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Codex uses a registration command; Cursor, Claude Code, VS Code and generic clients share one stdio config shape. (Source: Cloudeval docs)&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Cursor
&lt;/h3&gt;

&lt;p&gt;Add this to &lt;code&gt;.cursor/mcp.json&lt;/code&gt; (project) or &lt;code&gt;~/.cursor/mcp.json&lt;/code&gt; (global). Cursor's &lt;code&gt;${env:NAME}&lt;/code&gt; interpolation keeps the key out of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&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="nl"&gt;"cloudeval"&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="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stdio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&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="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@ganakailabs/cloudeval-cli"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"serve"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"--toolset"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"readonly"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&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="nl"&gt;"CLOUDEVAL_ACCESS_KEY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${env:CLOUDEVAL_ACCESS_KEY}"&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Cursor is launched from the dock and doesn't see your shell variables, Cursor also supports an &lt;code&gt;envFile&lt;/code&gt; for stdio servers. Point it at a git-ignored file.&lt;/p&gt;

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

&lt;p&gt;Claude Code wants its own options (like &lt;code&gt;--env&lt;/code&gt;) before &lt;code&gt;--&lt;/code&gt;, and the server command after it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add cloudeval &lt;span class="nt"&gt;--env&lt;/span&gt; &lt;span class="nv"&gt;CLOUDEVAL_ACCESS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CLOUDEVAL_ACCESS_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--&lt;/span&gt; npx &lt;span class="nt"&gt;-y&lt;/span&gt; @ganakailabs/cloudeval-cli mcp serve &lt;span class="nt"&gt;--toolset&lt;/span&gt; &lt;span class="nb"&gt;readonly

&lt;/span&gt;claude mcp get cloudeval     &lt;span class="c"&gt;# confirm it registered and connected&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This uses the default local scope, which is stored in &lt;code&gt;~/.claude.json&lt;/code&gt;. Avoid &lt;code&gt;--scope project&lt;/code&gt; here: that writes &lt;code&gt;.mcp.json&lt;/code&gt; into the repo, and you'd be one &lt;code&gt;git add .&lt;/code&gt; away from committing the key.&lt;/p&gt;

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

&lt;p&gt;You can register it with the documented one-liner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;codex mcp add cloudeval &lt;span class="nt"&gt;--&lt;/span&gt; cloudeval mcp serve &lt;span class="nt"&gt;--toolset&lt;/span&gt; &lt;span class="nb"&gt;readonly&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To forward the key from your environment instead of storing its value, edit &lt;code&gt;~/.codex/config.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[mcp_servers.cloudeval]&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"npx"&lt;/span&gt;
&lt;span class="py"&gt;args&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"@ganakailabs/cloudeval-cli"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"serve"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"--toolset"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"readonly"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;env_vars&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"CLOUDEVAL_ACCESS_KEY"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Anything else that speaks stdio
&lt;/h3&gt;

&lt;p&gt;Use the generic &lt;code&gt;mcpServers&lt;/code&gt; shape, which is the same entry published in the official MCP Registry under &lt;code&gt;io.github.ganakailabs/cloudeval&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"cloudeval"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"@ganakailabs/cloudeval-cli"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"serve"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"--toolset"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"readonly"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"CLOUDEVAL_ACCESS_KEY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;your scoped key&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;}}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Verify before you trust it
&lt;/h2&gt;

&lt;p&gt;Restart the client if it needs a restart, then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ask it to &lt;strong&gt;list the available Cloudeval tools&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Run something low-risk: &lt;code&gt;capabilities_get&lt;/code&gt; or &lt;code&gt;projects_list&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Check that the result shows the profile, base URL and auth mode you expect, and &lt;strong&gt;only&lt;/strong&gt; the project you scoped the key to.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If billing tools return permission errors, that's expected. The MCP Read-only key doesn't grant billing read access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Keep it read-only and widen on purpose
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;readonly&lt;/code&gt; is the default because review agents rarely need anything else. If a job calls for more, widen deliberately with one of the focused toolsets:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Toolset&lt;/th&gt;
&lt;th&gt;Use it for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;readonly&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Project, graph, report and capability reads (the default)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;graph&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Graph, timeline, diff, sync-run and insight reads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;validation&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;template_validate&lt;/code&gt;, &lt;code&gt;template_test&lt;/code&gt;, &lt;code&gt;template_parse&lt;/code&gt; and rule-catalogue reads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;reports&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Report runs, downloads and deeplinks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;billing&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Billing inspection, invoices and explicit checkout tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;all&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The full surface&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note what's &lt;strong&gt;not&lt;/strong&gt; in &lt;code&gt;readonly&lt;/code&gt;: &lt;code&gt;ask&lt;/code&gt;, &lt;code&gt;agent_profiles_run&lt;/code&gt;, &lt;code&gt;reports_run&lt;/code&gt; and the template-validation calls. Those start work on the Cloudeval side and can use credits. Your key also has to allow them.&lt;/p&gt;

&lt;p&gt;After changing toolsets, restart the client so it refreshes its tool list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Use Agent Profiles as reviewer lenses
&lt;/h2&gt;

&lt;p&gt;Agent Profiles change how an answer is organized, not what evidence is available. The public ids are &lt;code&gt;architecture&lt;/code&gt;, &lt;code&gt;cost&lt;/code&gt;, &lt;code&gt;triage&lt;/code&gt;, &lt;code&gt;remediation&lt;/code&gt;, &lt;code&gt;visual-explainer&lt;/code&gt;, &lt;code&gt;scripter&lt;/code&gt;, &lt;code&gt;change-reviewer&lt;/code&gt;, &lt;code&gt;evidence-auditor&lt;/code&gt; and &lt;code&gt;security-reviewer&lt;/code&gt;. There's no separate Well-Architected profile, because &lt;code&gt;architecture&lt;/code&gt; already includes that lens.&lt;/p&gt;

&lt;p&gt;On &lt;code&gt;readonly&lt;/code&gt;, the agent can discover them with &lt;code&gt;agent_profiles_list&lt;/code&gt; and &lt;code&gt;agent_profiles_get&lt;/code&gt;. Running one is excluded from &lt;code&gt;readonly&lt;/code&gt;, so either use a wider toolset or run it from your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cloudeval agents run change-reviewer &lt;span class="s2"&gt;"Review this pull request"&lt;/span&gt; &lt;span class="nt"&gt;--project&lt;/span&gt; &amp;lt;project-id&amp;gt;
cloudeval agents run security-reviewer &lt;span class="s2"&gt;"Review exposure and identity risk"&lt;/span&gt; &lt;span class="nt"&gt;--project&lt;/span&gt; &amp;lt;project-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;change-reviewer&lt;/code&gt; profile is built to return PASS/WARN/BLOCK with current, proposed and live evidence kept separate. If evidence is stale or missing, it should report an evidence gap rather than a pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Prompts that work
&lt;/h2&gt;

&lt;p&gt;Vague prompts get vague answers. These work better because each one names the evidence it wants:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Using the cloudeval tools, list my projects, then get the architecture graph for "&amp;lt;project name&amp;gt;".
Which resources have public network access, and which relationships connect them to data stores?
Cite the resource ID for each claim.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read the latest Well-Architected report for project &amp;lt;id&amp;gt;. Give me the five highest-severity findings
as a table: resource, finding, pillar, and the report reference. If any pillar is "Not assessed",
list it separately. Don't fill gaps with general advice.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I'm about to change infra/main.json in this repo. Using the project graph, tell me which resources
depend on the App Service plan defined there, so I know what this PR could affect.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Get the agent profile "cost" and summarize what it emphasizes. Then, using only the latest cost
report for project &amp;lt;id&amp;gt;, name the top three cost drivers and what evidence supports each one.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server also publishes MCP prompts (&lt;code&gt;cloudeval-architecture-review&lt;/code&gt;, &lt;code&gt;cloudeval-template-preflight&lt;/code&gt;, &lt;code&gt;cloudeval-impact-analysis&lt;/code&gt; and others) and resources such as &lt;code&gt;cloudeval://projects&lt;/code&gt; and &lt;code&gt;cloudeval://reports/latest&lt;/code&gt;. Clients that support prompts and resources show them in their prompt or &lt;code&gt;@&lt;/code&gt; menus.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjntbqhnu2xzx82vroi66.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjntbqhnu2xzx82vroi66.png" alt="Cloudeval agent answer grounded in selected resources and the diagram" width="800" height="521"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A useful agent answer stays tied to the project, the selected resources and the visible diagram. (Source: Cloudeval docs)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A habit worth keeping: &lt;strong&gt;ask the agent to name the project, resource or report behind every important claim.&lt;/strong&gt; If it can't, treat the answer as a hypothesis.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the common MCP setup mistakes?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Committing the key.&lt;/strong&gt; Use local or user scope and &lt;code&gt;${env:...}&lt;/code&gt; or &lt;code&gt;env_vars&lt;/code&gt;. Don't put it in Dockerfiles or project-scoped config you check in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expecting a URL.&lt;/strong&gt; This is a local stdio server. There's no Cloudeval-hosted remote MCP endpoint to paste into a web chat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assuming it sees live state.&lt;/strong&gt; A template-backed project describes the template you imported, not what's running. Check the sync time on live projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Letting the agent apply changes.&lt;/strong&gt; The agent can prepare a fix. A human reviews it, and the normal deployment pipeline ships it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is this the same as Microsoft's Azure MCP Server?
&lt;/h3&gt;

&lt;p&gt;No. Microsoft's Azure MCP Server queries live Azure resources. The Cloudeval MCP server gives the agent review context: project architecture graphs, saved cost and Well-Architected reports and the validation check catalogue. They can run side by side in the same client.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I add an MCP server to Claude Code?
&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;claude mcp add &amp;lt;name&amp;gt;&lt;/code&gt;, put Claude Code's own options such as &lt;code&gt;--env&lt;/code&gt; before &lt;code&gt;--&lt;/code&gt;, and the server command after it. Then run &lt;code&gt;claude mcp get &amp;lt;name&amp;gt;&lt;/code&gt; to confirm it connected. The default local scope keeps the entry out of your repo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does it work in VS Code?
&lt;/h3&gt;

&lt;p&gt;Yes. &lt;code&gt;cloudeval mcp setup vscode --dry-run&lt;/code&gt; prints the config for VS Code. The server is the same stdio command used by Cursor, Claude Code and Codex.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can the agent change my Azure resources over MCP?
&lt;/h3&gt;

&lt;p&gt;No. The default &lt;code&gt;readonly&lt;/code&gt; toolset reads projects, graphs, reports and the check catalogue. It can't deploy, change or remediate Azure resources. Tools that start work, such as report runs, are only in wider toolsets that you enable on purpose.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is there a hosted MCP URL I can paste into a web chat?
&lt;/h3&gt;

&lt;p&gt;No. It's a local stdio server that your client launches as a process. There's no Cloudeval-hosted remote MCP endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;MCP doesn't make an agent smarter about your architecture by itself. What helps is giving it scoped access to real evidence: a graph, saved reports and a check catalogue, with read-only as the default. Start with one project, one key and the &lt;code&gt;readonly&lt;/code&gt; toolset, then make the agent cite its sources. Widen access only when a specific job needs it.&lt;/p&gt;

&lt;p&gt;If you're choosing between MCP servers for Azure work, I wrote up &lt;a href="https://cloudeval.ai/answers/mcp-tools-for-azure-infrastructure-review?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=mcp-azure-review&amp;amp;utm_content=cta" rel="noopener noreferrer"&gt;which MCP tool fits which Azure review job&lt;/a&gt;. It covers Microsoft's &lt;a href="https://learn.microsoft.com/en-us/azure/developer/azure-mcp-server/overview" rel="noopener noreferrer"&gt;Azure MCP Server&lt;/a&gt; for live resource queries, Bicep tooling while authoring, and project-level review context. The full client reference is in the &lt;a href="https://docs.cloudeval.ai/agents/mcp-client-setup?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=mcp-azure-review&amp;amp;utm_content=docs" rel="noopener noreferrer"&gt;MCP client setup docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related on cloudeval.ai&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloudeval.ai/answers/mcp-tools-for-azure-infrastructure-review?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=mcp-azure-review&amp;amp;utm_content=related-answer" rel="noopener noreferrer"&gt;Which MCP tools help review Azure infrastructure?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloudeval.ai/answers/review-bicep-before-deployment?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=mcp-azure-review&amp;amp;utm_content=related-bicep" rel="noopener noreferrer"&gt;How to review a Bicep or ARM template before deployment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloudeval.ai/agents/profiles?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=mcp-azure-review&amp;amp;utm_content=related-profiles-docs" rel="noopener noreferrer"&gt;Agent Profiles reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloudeval.ai/compare?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=mcp-azure-review&amp;amp;utm_content=related-compare" rel="noopener noreferrer"&gt;Compare Cloudeval with other cloud review and diagram tools&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Try it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Want your own agent to answer from your architecture? Open the &lt;a href="https://cloudeval.ai/app?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=mcp-azure-review&amp;amp;utm_content=try-app" rel="noopener noreferrer"&gt;Cloudeval app&lt;/a&gt; and follow the &lt;a href="https://docs.cloudeval.ai/agents/mcp-client-setup?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=mcp-azure-review&amp;amp;utm_content=try-docs" rel="noopener noreferrer"&gt;MCP client setup guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About the author&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prateek Singh&lt;/strong&gt; is the founder of Ganak AI Labs and builds Cloudeval AI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cloudeval.ai/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=mcp-azure-review&amp;amp;utm_content=author" rel="noopener noreferrer"&gt;cloudeval.ai&lt;/a&gt; · &lt;a href="https://docs.cloudeval.ai/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=mcp-azure-review&amp;amp;utm_content=author" rel="noopener noreferrer"&gt;Docs&lt;/a&gt; · &lt;a href="https://www.youtube.com/@GanakAILabs" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt; · &lt;a href="https://github.com/ganakailabs" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; · &lt;a href="https://www.linkedin.com/in/prateekkumarsingh/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>azure</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
