Skip to content
Deployment
Skill

/scaffold

Generate deployment-ready infrastructure code from an architecture plan, verify it with adversarial self-review, and bridge to validation — all without deploying.

From plugin
azure
1.4k37 skills1 MCP
Install
$ npx -y skills add microsoft/azure-skills --skill scaffold --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/scaffold

Context preview

The summary Claude sees to decide when to auto-load this skill.

Generate deployment-ready infrastructure code from an architecture plan, verify it with adversarial self-review, and bridge to validation — all without deploying.

SKILL.md

scaffold.SKILL.md

Azure App Onboard Scaffold — IaC Generation + Self-Review

Generate deployment-ready infrastructure code from an architecture plan, verify it with adversarial self-review, and bridge to validation — all without deploying.

Quick Reference

| Property | Value | |----------|-------| | Parent | [azure-app-onboard](../SKILL.md) | | Best for | Turning `prepare-plan.json` service list into Bicep templates with secure-by-default patterns | | Inputs | `prepare-plan.json` (services, naming, quotas), `context.json` (overrides, components, repo info) | | Outputs | `scaffold-manifest.json`, generated IaC files in `infra/` | | Pipeline position | Phase 3 of 4: prereq → prepare → **scaffold** → deploy | | IaC format | Bicep (v1 default). Terraform when existing `.tf` detected or user override. |

When to Use This Skill

Invoked by the `azure-app-onboard` orchestrator at Phase 3 when `prepare-plan.json` exists with `services[]`. Not directly user-routable in v1.

> **Return to orchestrator:** When complete, return control to `azure-app-onboard`. Do NOT directly invoke deploy — the orchestrator manages phase transitions.

When NOT to Use

| Scenario | Use Instead | |----------|-------------| | User-triggered IaC (no `prepare-plan.json`) | `azure-prepare` | | Subscription-scope landing zones | `azure-enterprise-infra-planner` | | Execute deployment (`azd up`) | `azure-deploy` (do NOT invoke from AppOnboard pipeline) |

MCP Tools

> See [shared tools](../references/mcp-tool-reference.md) for cross-phase tools and global parameters. See [scaffold tools](references/mcp-tools.md) for full parameter tables.

| Tool | Sub-command | Purpose | Parameters | |------|-----------|---------|------------| | `mcp_azure_mcp_bicepschema` | `bicepschema_get` | ARM resource type schemas | `resource_type` (Required), `api_version` (Optional) | | `mcp_bicep_list_avm_metadata` | *(flat)* | AVM module catalog | None | | `mcp_bicep_get_bicep_best_practices` | *(flat)* | Bicep best practices | None | | `mcp_bicep_get_az_resource_type_schema` | *(flat)* | ARM resource type JSON schema | `azResourceType`, `apiVersion` (Required) | | `mcp_bicep_build_bicep` | *(flat)* | Validate `.bicep` files (self-review L3) | `filePath` (Required) | | `mcp_bicep_format_bicep_file` | *(flat)* | Format `.bicep` files (LF enforcement) | `filePath` (Required) | | `mcp_azure_mcp_deploy` | `deploy_iac_rules_get` | IaC best practices and rules | `deployment-tool`, `iac-type`, `resource-types` | | `mcp_azure_mcp_deploy` | `deploy_pipeline_guidance_get` | CI/CD pipeline config | `is-azd-project`, `pipeline-platform`, `deploy-option` | | `mcp_azure_mcp_get_azure_bestpractices` | `get_azure_bestpractices_get` | SDK/Functions best practices | `resource`, `action` | | `mcp_azure_mcp_azureterraformbestpractices` | *(flat)* | Terraform patterns (TF path only) | `resource_type` (Required) |

Workflow

**Session folder:** `.copilot-azure/sessions/{uuid}/` — reads `prepare-plan.json` + `context.json`, writes `scaffold-manifest.json`.

DETECT (Steps 1–4)

1. **Read `prepare-plan.json`** — verify `services[]` exists, read `naming` config (especially `naming.resourcePrefix`, `naming.suffix`, `naming.resources[]`). Read resource group name from `context.json.azure.resourceGroup`. ⛔ **Use EXACTLY these names in generated IaC — do NOT invent names, derive them from `environmentName`, or append your own suffixes.** ⛔ **Use EXACTLY the names from `prepare-plan.json.naming.resources[]` as Bicep parameters. Do NOT derive names with `take()`, `substring()`, or string manipulation. The plan is the source of truth.** Missing → trigger prepare backfill via `azure-app-onboard` orchestrator. 2. **Read `context.json`** — check `overrides[]` for `iacFormat` preference, `detectedInfra[]` for existing `.tf`, `detectedInfraProvider` for cloud provider classification. 3. **Check workspace for existing IaC** — ⛔ **Skip** if `context.json.overrides[]` contains `ignoreExistingInfra: true`. Otherwise:

  • **Azure IaC** (`.bicep`, `azure.yaml`, `.tf` with `azurerm`): `ask_user` → "Start fresh" (rename `infra/` to `infra.bak/`) or "Use existing" (route to `azure-prepare`, stop pipeline).
  • **Non-Azure IaC** (`.tf` with GCP/AWS): respect `context.json.overrides[].iacFormat` from prepare. Default: Bicep alongside existing TF.
  • **Unknown TF** (`detectedInfraProvider.terraform` == `"unknown"`): ask user which provider before routing.
  • **No IaC**: continue.

4. **Determine compute targets** — Check which compute targets are in the plan (App Service/Functions, Container Apps, or both) and whether PostgreSQL/Redis is present. Do NOT read any reference files — pass this info to the sub-agent at Step 5. 4b. **Pre-check API versions (main thread)** — MCP tool access is unreliable in `task` agents — call these in the main thread before dispatching. Call `mcp_bicep_list_az_resource_types_for_provider` (or `bicep-list_az_resource_types_for_provider`) once per provider namespace in `prepare-plan.json.services[]` (e.g., `Microsoft.Web`, `Microsoft.App`, `Microsoft.DBforPostgreSQL`, `Microsoft.Cache`, `Microsoft.KeyVault`, `Microsoft.ContainerRegistry`). Extract the latest GA API version (no `-preview`) for each resource type. Build an `apiVersions` map and pass it to the IaC gen sub-agent at Step 5. Fallback: if MCP unavailable, run `az provider show --namespace {ns} --query "resourceTypes[?resourceType=='{type}'].apiVersions[?!contains(@, 'preview')] | [0][0]" -o tsv` per resource type — this filters to GA-only and picks the latest. Pass `"MCP unavailable"` only if both MCP AND CLI fail. Sub-agent still validates generated Bicep via `az bicep build`.

ACTION (Steps 5–12)

> ⛔ **File boundary:** NEVER modify files outside `infra/`, `.copilot-azure/`. Scaffold only writes files — no install/build commands.

> ⛔ **Sub-agent delegation is MANDATORY for Steps 5, 6–9, and 10–12.** Each step reads its `subagent-*.md` template, then dispatches a `task` call. Do NOT read any re

Read more
Ships withazure

Azure work is not just a code problem. It is a decision problem: which service fits this app, what needs to be validated before deployment, which tools should run, and what guardrails matter.

Get the whole plugin

Other skills on azure.