Skip to content

Commit 14e401c

Browse files
Merge pull request #312531 from mumian/0302-snapshot
Document Bicep CLI snapshot
2 parents fef4d5b + cb61f24 commit 14e401c

2 files changed

Lines changed: 145 additions & 26 deletions

File tree

articles/azure-resource-manager/bicep/bicep-cli.md

Lines changed: 141 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Bicep CLI commands
33
description: Learn about the commands that you can use in the Bicep CLI. These commands include building JSON Azure Resource Manager templates from Bicep.
44
ms.topic: reference
5-
ms.date: 12/02/2025
5+
ms.date: 03/02/2026
66
ms.custom: devx-track-azurecli, devx-track-bicep, devx-track-arm-template
77
---
88

@@ -16,14 +16,14 @@ This guidance shows how to run the commands in the Azure CLI. When running comma
1616

1717
The `build` command converts a Bicep file to a JSON Azure Resource Manager template (ARM template). Typically, you don't need to run this command because it runs automatically when you deploy a Bicep file. Run it manually when you want to see the JSON ARM template that's created from your Bicep file.
1818

19-
Using any of following Bicep features automatically enables language version 2.0 code generation:
19+
Using any of the following Bicep features automatically enables language version 2.0 code generation:
2020

2121
* [user-defined types](../bicep/user-defined-data-types.md)
2222
* [user-defined functions](../bicep/user-defined-functions.md)
2323
* [compile-time imports](../bicep/bicep-import.md)
2424
* [experimental features](../bicep/bicep-config.md#enable-experimental-features)
2525

26-
The following example converts a Bicep file named _main.bicep_ to an ARM template named _main.json_. The new file is created in the same directory as the Bicep file:
26+
The following example converts a Bicep file named *main.bicep* to an ARM template named *main.json*. The new file is created in the same directory as the Bicep file:
2727

2828
# [Bicep CLI](#tab/bicep-cli)
2929

@@ -39,7 +39,7 @@ az bicep build --file main.bicep
3939

4040
---
4141

42-
The next example saves _main.json_ to a different directory:
42+
The next example saves *main.json* to a different directory:
4343

4444
# [Bicep CLI](#tab/bicep-cli)
4545

@@ -55,7 +55,7 @@ az bicep build --file main.bicep --outdir c:\jsontemplates
5555

5656
---
5757

58-
The next example specifies the name and location of the file to be created:
58+
The following example specifies the name and location of the file to create:
5959

6060
# [Bicep CLI](#tab/bicep-cli)
6161

@@ -92,7 +92,7 @@ If your Bicep file includes a module that references an external registry, the `
9292
> [!NOTE]
9393
> The `restore` command doesn't refresh the cache. For more information, see [restore](#restore).
9494
95-
To not call restore automatically, use the `--no-restore` switch:
95+
To prevent automatic restore, use the `--no-restore` switch:
9696

9797
# [Bicep CLI](#tab/bicep-cli)
9898

@@ -156,7 +156,7 @@ az bicep decompile --file main.json
156156

157157
---
158158

159-
This command creates a file named _main.bicep_ in the same directory as _main.json_. If _main.bicep_ exists in the same directory, use the **--force** switch to overwrite the existing Bicep file.
159+
This command creates a file named _main.bicep_ in the same directory as _main.json_. If _main.bicep_ exists in the same directory, use the `--force` switch to overwrite the existing Bicep file.
160160

161161
For more information about using this command, see [Decompile JSON ARM template to Bicep](decompile.md).
162162

@@ -178,11 +178,11 @@ az bicep decompile-params --file azuredeploy.parameters.json --bicep-file ./dir/
178178

179179
---
180180

181-
This command decompiles an _azuredeploy.parameters.json_ parameters file into an _azuredeploy.parameters.bicepparam_ file. `--bicep-file` specifies the path to the Bicep file (relative to the `.bicepparam` file) that's referenced in the `using` declaration.
181+
This command decompiles an _azuredeploy.parameters.json_ parameters file into an _azuredeploy.parameters.bicepparam_ file. Use `--bicep-file` to specify the path to the Bicep file (relative to the `.bicepparam` file) that's referenced in the `using` declaration.
182182

183183
## format
184184

185-
The `format` command formats a Bicep file so that it follows the recommended style conventions. Think of it like a "code formatter" or "prettier" for your Bicep files. It has the same function as the `SHIFT+ALT+F` shortcut in Visual Studio Code.
185+
The `format` command formats a Bicep file so that it follows the recommended style conventions. Think of it as a code formatter or "prettier" for your Bicep files. It has the same function as the `SHIFT+ALT+F` shortcut in Visual Studio Code.
186186

187187
# [Bicep CLI](#tab/bicep-cli)
188188

@@ -200,7 +200,7 @@ az bicep format --file main.bicep
200200

201201
## generate-params
202202

203-
The `generate-params` command builds a parameters file from the given Bicep file, updates if there's an existing parameters file.
203+
The `generate-params` command builds a parameters file from the given Bicep file and updates it if there's an existing parameters file.
204204

205205
# [Bicep CLI](#tab/bicep-cli)
206206

@@ -252,7 +252,7 @@ az bicep install
252252

253253
---
254254

255-
To install a specific version:
255+
To install a specific version, use the following command:
256256

257257
# [Bicep CLI](#tab/bicep-cli)
258258

@@ -268,9 +268,9 @@ az bicep install --version v0.37.4
268268

269269
## jsonrpc
270270

271-
The `jsonrpc` command enables running the Bicep CLI with a JSON-RPC interface, allowing for programmatic interaction with structured output and avoiding cold-start delays when compiling multiple files. This setup also supports building libraries to interact with Bicep files programmatically in non-.NET languages.
271+
The `jsonrpc` command runs the Bicep CLI with a JSON-RPC interface. By using this interface, you can interact programmatically with structured output. You also avoid cold-start delays when compiling multiple files. This setup supports building libraries to interact with Bicep files programmatically in non-.NET languages.
272272

273-
The wire format for sending and receiving input/output is header-delimited, using the following structure, where `\r` and `\n` represent carriage return and line feed characters:
273+
The wire format for sending and receiving input and output is header-delimited. It uses the following structure, where `\r` and `\n` represent carriage return and line feed characters:
274274

275275
```
276276
Content-Length: <length>\r\n\r\n<message>\r\n\r\n
@@ -347,8 +347,8 @@ The following methods are available through the JSON-RPC interface:
347347
}
348348
```
349349

350-
For the available methods & request/response bodies, see [`ICliJsonRpcProtocol.cs`](https://github.com/Azure/bicep/blob/main/src/Bicep.Cli/Rpc/ICliJsonRpcProtocol.cs).
351-
For an example establishing a JSONRPC connection and interacting with Bicep files programmatically using Node, see [`jsonrpc.test.ts`](https://github.com/Azure/bicep/blob/main/src/Bicep.Cli.E2eTests/src/local/jsonrpc.test.ts).
350+
For the available methods and request and response bodies, see [`ICliJsonRpcProtocol.cs`](https://github.com/Azure/bicep/blob/main/src/Bicep.Cli/Rpc/ICliJsonRpcProtocol.cs).
351+
For an example establishing a JSONRPC connection and interacting with Bicep files programmatically by using Node, see [`jsonrpc.test.ts`](https://github.com/Azure/bicep/blob/main/src/Bicep.Cli.E2eTests/src/local/jsonrpc.test.ts).
352352

353353
### Usage for named pipe
354354

@@ -368,7 +368,7 @@ N/A
368368

369369
---
370370

371-
To connect to a named pipe on OSX/Linux:
371+
To connect to a named pipe on macOS or Linux:
372372

373373
# [Bicep CLI](#tab/bicep-cli)
374374

@@ -432,7 +432,7 @@ N/A
432432

433433
### Usage for stdin and stdout
434434

435-
Use the following syntax and `stdin` and `stdout` for messages to run the JSONRPC interface:
435+
To run the JSONRPC interface, use the following syntax. Use `stdin` and `stdout` for messages:
436436

437437
# [Bicep CLI](#tab/bicep-cli)
438438

@@ -469,7 +469,7 @@ If your Bicep file includes a module that references an external registry, the `
469469
> [!NOTE]
470470
> The `restore` command doesn't refresh the cache. For more information, see [restore](#restore).
471471
472-
To not call restore automatically, use the `--no-restore` switch:
472+
To prevent automatic restore, use the `--no-restore` switch:
473473

474474
# [Bicep CLI](#tab/bicep-cli)
475475

@@ -548,7 +548,7 @@ The command returns an array of available versions:
548548

549549
## publish
550550

551-
The `publish` command adds a module to a registry. The Azure container registry must exist and the account publishing to the registry must have the correct permissions. For more information about setting up a module registry, see [Use private registry for Bicep modules](private-module-registry.md). To publish a module, the account must have the correct profile and permissions to access the registry. You can configure the profile and credential precedence for authenticating to the registry in the [Bicep config file](./bicep-config-modules.md#configure-profiles-and-credentials).
551+
The `publish` command adds a module to a registry. The Azure container registry must exist, and the account publishing to the registry must have the correct permissions. For more information about setting up a module registry, see [Use private registry for Bicep modules](private-module-registry.md). To publish a module, the account must have the correct profile and permissions to access the registry. You can configure the profile and credential precedence for authenticating to the registry in the [Bicep config file](./bicep-config-modules.md#configure-profiles-and-credentials).
552552

553553
After publishing the file to the registry, you can [reference it in a module](modules.md#file-in-registry).
554554

@@ -590,11 +590,11 @@ az bicep publish --file storage.bicep --target br:exampleregistry.azurecr.io/bic
590590
The `publish` command doesn't recognize aliases specified in a [_bicepconfig.json_ file](bicep-config-modules.md). Provide the full module path.
591591

592592
> [!WARNING]
593-
> Publishing to the same target overwrites the old module. We recommend that you increment the version when updating.
593+
> Publishing to the same target overwrites the old module. Increment the version when updating.
594594
595595
## restore
596596

597-
When your Bicep file uses modules that are published to a registry, the `restore` command gets copies of all the required modules from the registry. It stores those copies in a local cache. A Bicep file can only be built when the external files are available in the local cache. Normally, running restore isn't necessary as it's automatically triggered by the build process.
597+
When your Bicep file uses modules that you publish to a registry, the `restore` command gets copies of all the required modules from the registry. It stores those copies in a local cache. A Bicep file can only be built when the external files are available in the local cache. Normally, running restore isn't necessary as it's automatically triggered by the build process.
598598

599599
To restore external modules to the local cache, the account must have the correct profile and permissions to access the registry. You can configure the [profile and credential precedence](./bicep-config-modules.md#configure-profiles-and-credentials) for authenticating to the registry in the Bicep config file.
600600

@@ -616,7 +616,7 @@ az bicep restore --file <bicep-file> [--force]
616616

617617
---
618618

619-
The Bicep file you provide is the file you wish to deploy. It must contain a module that links to a registry. For example, you can restore the following file:
619+
The Bicep file you provide is the file you want to deploy. It must contain a module that links to a registry. For example, you can restore the following file:
620620

621621
```bicep
622622
module stgModule 'br:exampleregistry.azurecr.io/bicep/modules/storage:v1' = {
@@ -627,7 +627,7 @@ module stgModule 'br:exampleregistry.azurecr.io/bicep/modules/storage:v1' = {
627627
}
628628
```
629629

630-
The local cache is found in:
630+
You find the local cache in:
631631

632632
* On Windows
633633

@@ -649,6 +649,123 @@ The local cache is found in:
649649
650650
The `restore` command doesn't refresh the cache if a module is already cached. To refresh the cache, you can either delete the module path from the cache or use the `--force` switch with the `restore` command.
651651
652+
## snapshot
653+
654+
By using Bicep CLI v0.41.2 or newer, you can use the `snapshot` command to create a normalized, deterministic representation of a Bicep deployment from a `.bicepparam` file. You can compare this snapshot with later snapshots to understand what changes a refactor would cause, without deploying anything to Azure. This command is particularly useful for:
655+
656+
* **Visual Diffs**: Seeing exactly how a refactor (like moving code into a module) changes the underlying resource definitions.
657+
* **Complex Expressions**: Understanding what a complex string or variable actually evaluates to before deployment.
658+
* **CI/CD Validation**: Automatically catching unintended changes in infrastructure logic during pull requests.
659+
660+
### Create a snapshot
661+
662+
This command generates a `.snapshot.json` file. This file is "normalized," meaning it removes noise like module boundaries so you can focus on the resources themselves.
663+
664+
#### [Bicep CLI](#tab/bicep-cli)
665+
666+
```bicepcli
667+
bicep snapshot --mode overwrite <bicep-param-file>
668+
```
669+
670+
#### [Azure CLI](#tab/azure-cli)
671+
672+
`az bicep snapshot` doesn't exist. You must run `bicep snapshot` directly.
673+
674+
---
675+
676+
The following JSON file shows a snapshot example:
677+
678+
```json
679+
{
680+
"predictedResources": [
681+
{
682+
"id": "[format('/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Storage/storageAccounts/stmyappstorage001', subscription().subscriptionId, resourceGroup().name)]",
683+
"type": "Microsoft.Storage/storageAccounts",
684+
"name": "stmyappstorage001",
685+
"apiVersion": "2025-01-01",
686+
"location": "eastus",
687+
"sku": {
688+
"name": "Standard_LRS"
689+
},
690+
"kind": "StorageV2"
691+
}
692+
],
693+
"diagnostics": []
694+
}
695+
```
696+
697+
### Validate changes
698+
699+
After creating a snapshot, run the command in validate mode. It compares your current Bicep code against the saved snapshot and shows a visual diff, much like the [what-if](./deploy-what-if.md) command but entirely local.
700+
701+
#### [Bicep CLI](#tab/bicep-cli)
702+
703+
```bicepcli
704+
bicep snapshot --mode validate <bicep-param-file>
705+
```
706+
707+
#### [Azure CLI](#tab/azure-cli)
708+
709+
`az bicep snapshot` doesn't exist. You must run `bicep snapshot` directly.
710+
711+
---
712+
713+
A sample output looks like:
714+
715+
```
716+
PS C:\bicep> bicep snapshot --mode validate main.bicepparam
717+
Snapshot validation failed. Expected no changes, but found the following:
718+
719+
Scope: <unknown>
720+
721+
~ [format('/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Storage/storageAccounts/stmyappstorage001', subscription().subscriptionId, resourceGroup().name)]
722+
~ apiVersion: "2025-01-01" => "2025-06-01"
723+
~ sku.name: "Standard_LRS" => "Standard_GRS"
724+
```
725+
726+
"Snapshot validation failed" indicates differences between the two snapshots.
727+
728+
Snapshot and What-if have these differences:
729+
730+
| Feature | `bicep snapshot` | `az deployment group what-if` |
731+
| :--- | :--- | :--- |
732+
| **Execution** | **Local only** (Offline) | **Cloud-based** (Online) |
733+
| **Comparison** | Compares code vs. a saved file | Compares code vs. live Azure state |
734+
| **Speed** | Extremely fast | Slower (requires API calls) |
735+
| **Use Case** | Refactoring and logic testing | Final pre-deployment check |
736+
737+
### Provide context
738+
739+
When running bicep snapshot, the CLI performs a local evaluation of your code. Since it doesn't talk to Azure, it cannot "ask" the cloud for your Subscription ID or the current Resource Group name.
740+
741+
If your code uses environment functions (like `subscription().id`), the snapshot will fail or return placeholders unless you provide specific context via CLI arguments.
742+
743+
To simulate a real deployment environment, you can pass the following flags:
744+
745+
| Argument | Purpose | Example Value |
746+
| :--- | :--- | :--- |
747+
| `--subscription-id` | Replaces the value returned by `subscription().subscriptionId` | `00000000-1111-2222-3333-444444444444` |
748+
| `--resource-group` | Replaces the value returned by `resourceGroup().name` | `my-production-rg` |
749+
| `--location` | Sets the default location for `deployment().location` | `westeurope` |
750+
| `--tenant-id` | Replaces the value returned by `tenant().tenantId` | `72f988bf-86f1-41af-91ab-2d7cd011db47` |
751+
| `--management-group` | Replaces the value returned by `managementGroup().name` | `my-corp-mg` |
752+
753+
#### [Bicep CLI](#tab/bicep-cli)
754+
755+
```bicepcli
756+
bicep snapshot main.bicepparam \
757+
--subscription-id 00000000-0000-0000-0000-000000000000 \
758+
--resource-group my-temp-rg \
759+
--location eastus \
760+
--mode overwrite
761+
```
762+
763+
#### [Azure CLI](#tab/azure-cli)
764+
765+
`az bicep snapshot` doesn't exist. You must run `bicep snapshot` directly.
766+
767+
---
768+
652769
## upgrade
653770

654771
The `upgrade` command updates your installed version with the latest version. This command is only available through the Azure CLI.
@@ -675,7 +792,7 @@ The `version` command returns your installed version:
675792
bicep --version
676793
```
677794

678-
If the Bicep CLI hasn't been installed, you'll see an error message stating that the Bicep CLI wasn't found.
795+
If you didn't install the Bicep CLI, you see an error message stating that the Bicep CLI wasn't found.
679796

680797
# [Azure CLI](#tab/azure-cli)
681798

articles/azure-resource-manager/bicep/deploy-what-if.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: 'Bicep What-If: Preview Changes Before Deployment'
33
description: Determine what changes will happen to your resources before deploying a Bicep file.
44
ms.topic: article
5-
ms.date: 01/07/2026
5+
ms.date: 03/03/2026
66
ms.custom:
77
- devx-track-bicep, devx-track-azurecli, devx-track-azurepowershell
88
- ai-gen-docs-bap
@@ -15,6 +15,8 @@ ms.custom:
1515

1616
Before deploying a Bicep file, you can preview the changes that will happen. Azure Resource Manager provides the what-if operation to let you see how resources will change if you deploy the Bicep file. The what-if operation doesn't make any changes to existing resources. Instead, it predicts the changes if the specified Bicep file is deployed.
1717

18+
Similar to what-if, the [`bicep snapshot`](./bicep-cli.md#snapshot) command performs local-only testing by generating and comparing a normalized JSON representation of your infrastructure to catch unintended logic changes without requiring an Azure connection. For a comparison, see [Comparison snapshot vs what-if](./bicep-cli.md#validate-changes).
19+
1820
You can use the what-if operation with [Visual Studio Code](./deploy-visual-studio-code.md#deployment-pane), Azure PowerShell, Azure CLI, or REST API operations. What-if is supported for resource group, subscription, management group, and tenant level deployments.
1921

2022
During What-If operations, the evaluation and expansion of `templateLink` aren't supported. As a result, any resources deployed using template links within nested deployments, including template spec references, won't be visible in the What-If operation results.
@@ -125,7 +127,7 @@ For REST API, use:
125127

126128
You can use the what-if operation through the Azure SDKs.
127129

128-
- For Python, use [what-if](/python/api/azure-mgmt-resource/azure.mgmt.resource.resources.v2019_10_01.operations.deploymentsoperations#what-if-resource-group-name--deployment-name--properties--location-none--custom-headers-none--raw-false--polling-true----operation-config-).
130+
- For Python, use [what-if](/python/api/azure-mgmt-resource-deployments/azure.mgmt.resource.deployments.models.whatifchange).
129131
- For Java, use [DeploymentWhatIf Class](/java/api/com.azure.resourcemanager.resources.models.deploymentwhatif).
130132
- For .NET, use [DeploymentWhatIf Class](/dotnet/api/microsoft.azure.management.resourcemanager.models.deploymentwhatif).
131133

0 commit comments

Comments
 (0)