Tear down a Git-Ape deployment by ID. Reads `state.json` under `.azure/deployments/<id>/` to delete the Azure Deployment Stack and purge soft-deleted Key Vault / Cognitive Services. Refuses to run without `state.json`. Use for any local CLI or VS Code Git-Ape teardown so the result matches the CI destroy workflow.
npx skills add https://github.com/Azure/git-ape --skill azure-stack-destroy
Destroy a Git-Ape deployment by deleting its subscription-scoped Azure Deployment Stack in a single idempotent call (az stack sub delete --action-on-unmanage deleteAll --bypass-stack-out-of-sync-error true). The stack owns every resource the matching deploy created — across resource groups and subscription scope — so one delete cleans up everything.
After the stack is gone, this skill performs a soft-delete purge sweep for resource types that linger after deletion (Key Vault, Cognitive Services, App Configuration, API Management, ML workspaces, Recovery Services vaults). Resources flagged purgeProtected: true in state.json are intentionally retained.
This skill mirrors .github/workflows/git-ape-destroy.yml so local destroys and CI destroys are interchangeable.
Trigger this skill when the user wants to tear down a Git-Ape deployment they previously created:
state.json is still on diskgit-ape-destroy.yml does in CIaz group deleteFor any deployment Git-Ape created, this skill is the correct tool — do not suggest az group delete on its own. Reasons:
az group delete cleans only one RG.state.json and metadata.json to terminal status (destroyed, retained-soft-deleted, etc.) so the next operation sees an accurate view.Refuse to invoke this skill in any of these cases:
state.json on disk. Hard prerequisite — see below. Without it, recommend re-running deploy or aborting.az group create). Suggest az group delete --name <rg> --yes directly instead.azure-stack-deploy for those.azure-stack-deploy — same stack, same state.json key (stackId)az group delete against a Git-Ape deployment (don't — you'll miss soft-delete cleanup and multi-RG resources)| Tool | Why |
|------|-----|
| az (Azure CLI ≥ 2.59) | az stack sub delete --bypass-stack-out-of-sync-error requires a recent CLI |
| jq | Read state.json |
| bash ≥ 4 OR PowerShell 7+ | Either runner works |
| Active az login | Must be the same subscription where the stack lives |
| Existing state.json under .azure/deployments/<id>/ | Source of truth for stackId, managedResources, softDeletable, purgeProtected |
> Hard prerequisite: state.json under .azure/deployments/<id>/. Without it this skill aborts — it has no idea which stack, resource groups, or soft-deletables to clean up. Do NOT hand-write state.json; re-run the matching azure-stack-deploy for that deployment ID first, or use az group delete directly on a known resource group (a non-Git-Ape teardown, outside this skill's scope).
The scripts default to fast mode (interactive default). The CI workflow keeps sync mode (deterministic).
| | How | Wait time (small VNet stack) | When to use |
|--|--|--|--|
| Fast (default) | Background the az stack sub delete call, then poll managed RGs with az group exists | ~2 min | Local CLI / VS Code use; user wants quick feedback |
| Sync (--wait / -Wait) | az stack sub delete ... --yes (blocks until stack metadata is fully cleaned) | ~5 min | CI pipelines (default in git-ape-destroy.yml); when you need every Azure-side cleanup completed before the script exits |
The Azure CLI does not expose --no-wait on az stack sub delete, so the fast path runs the same command as a detached background process. In fast mode the stack-metadata cleanup continues asynchronously in Azure after the script returns. The next destroy of the same deploymentId is idempotent: if the stack is still finalizing, az stack sub show will return it and the script will simply pick up where Azure left off.
DEPLOYMENT_ID="deploy-20260506-001"
DEPLOYMENT_PATH=".azure/deployments/$DEPLOYMENT_ID"
[[ -f "$DEPLOYMENT_PATH/state.json" ]] || { echo "state.json missing — cannot destroy"; exit 1; }
.github/skills/azure-stack-destroy/scripts/destroy-stack.sh \
--deployment-id "$DEPLOYMENT_ID"
Skip the confirmation prompt (use only in automation):
.github/skills/azure-stack-destroy/scripts/destroy-stack.sh \
--deployment-id "$DEPLOYMENT_ID" \
--yes
Force CI-equivalent sync wait (default for the CI workflow; opt-in for the script):
.github/skills/azure-stack-destroy/scripts/destroy-stack.sh \
--deployment-id "$DEPLOYMENT_ID" \
--yes --wait
PowerShell equivalents:
.github/skills/azure-stack-destroy/scripts/destroy-stack.ps1 -DeploymentId "$DEPLOYMENT_ID"
.github/skills/azure-stack-destroy/scripts/destroy-stack.ps1 -DeploymentId "$DEPLOYMENT_ID" -Yes
.github/skills/azure-stack-destroy/scripts/destroy-stack.ps1 -DeploymentId "$DEPLOYMENT_ID" -Yes -Wait
state.json and extracts stackId, deployMethod, resourceGroup, managedResources[], softDeletable[]destroy confirmation (unless --yes)stackId present):az stack sub delete --action-on-unmanage deleteAll --bypass-stack-out-of-sync-error true --yesstackId, only resourceGroup): az group delete --name <rg> --yessoftDeletable resource not marked purgeProtected:az keyvault list-deleted + az keyvault purgeaz cognitiveservices account purgepurgeResults[] with status: skipped-natural-expiryaz deployment sub delete) to stay under the 800/scope limitstate.json and metadata.json with terminal status:| Status | Meaning |
|--------|---------|
| destroyed | Stack/RG gone and all soft-deletables purged or absent |
| retained-soft-deleted | Stack gone but at least one soft-deletable retained (purge-protected or purge failed) |
| partially-destroyed | Stack delete partially failed |
| destroy-failed | Stack/RG delete failed entirely |
| already-destroyed | Stack and RG were already gone before this call |
=== Destroy Summary ===
Status: destroyed
Duration: 87s
=======================
Or, when something is intentionally retained:
=== Destroy Summary ===
Status: retained-soft-deleted
Duration: 92s
Retained: 1 soft-deleted resource(s) (purge-protected)
=======================
state.json gains destroyedAt, destroyedBy, destroyDuration, and a purgeResults[] array describing each soft-deletable's outcome.
| Flag (bash) | Param (pwsh) | Required | Description |
|-------------|--------------|----------|-------------|
| --deployment-id <id> | -DeploymentId <id> | yes | Folder name under .azure/deployments/ |
| --yes | -Yes | no | Skip the typed destroy confirmation prompt (CI-only) |
| --wait | -Wait | no | Sync mode: block until Azure has cleaned up stack metadata. Matches the CI workflow. Slower (~3-4×) but fully deterministic. |
| --poll-timeout <sec> | -PollTimeout <sec> | no | Fast-mode timeout per managed RG poll (default 600s) |
| Symptom | Likely cause | Recovery |
|---------|--------------|----------|
| state.json missing | Deployment never reached the state-write phase, or was hand-edited | Re-deploy (idempotent on stack name) then destroy, OR delete the .azure/deployments/<id>/ folder if Azure has nothing |
| Stack out of sync despite --bypass-stack-out-of-sync-error | Old CLI version | Upgrade az to ≥ 2.59 |
| Key Vault purge fails | Vault is purge-protected (purgeProtected: true) | Expected — wait 7-90 days for soft-delete window to expire, or purge manually after disabling protection |
| Cannot delete resource group …/InUseSubnetCannotBeDeleted | A resource outside the stack references one inside (e.g. external subnet peered to a deleted VNet) | Inspect externalReferences[] in state.json; remove the reference and rerun |
azure-stack-deploy — the matching deploy skill (writes the state.json this skill consumes)azure-drift-detector — check for unmanaged drift BEFORE destroyazure-resource-visualizer — visualize what's in the stack before tearing it downRun Python code in the cloud with serverless containers, GPUs, and autoscaling. Use when deploying ML models, running batch processing jobs, scheduling compute-intensive tasks, or serving APIs that require GPU acceleration or dynamic scaling.
Advanced GitHub Actions workflow automation with AI swarm coordination, intelligent CI/CD pipelines, and comprehensive repository management
Google Cloud Platform CLI - manage GCP resources including Compute Engine, Cloud Run, GKE, Cloud Functions, Storage, BigQuery, and more.
Expert backend architect specializing in scalable API design, microservices architecture, and distributed systems. Masters REST/GraphQL/gRPC APIs, event-driven architectures, service mesh patterns, and modern backend frameworks. Handles service boundary definition, inter-service communication, resilience patterns, and observability. Use PROACTIVELY when creating new backend services or APIs.
Run Python code in the cloud with serverless containers, GPUs, and autoscaling. Use when deploying ML models, running batch processing jobs, scheduling compute-intensive tasks, or serving APIs that require GPU acceleration or dynamic scaling.
Aspire skill covering the Aspire CLI, AppHost orchestration, service discovery, integrations, MCP server, VS Code extension, Dev Containers, GitHub Codespaces, templates, dashboard, and deployment. Use when the user asks to create, run, debug, configure, deploy, or troubleshoot an Aspire distributed application.
Audits Python + BigQuery pipelines for cost safety, idempotency, and production readiness. Returns a structured report with exact patch locations.
Microsoft Store Developer CLI (msstore) for publishing Windows applications to the Microsoft Store. Use when asked to configure Store credentials, list Store apps, check submission status, publish submissions, manage package flights, set up CI/CD for Store publishing, or integrate with Partner Center. Supports Windows App SDK/WinUI, UWP, .NET MAUI, Flutter, Electron, React Native, and PWA applications.
Take azure/azure-stack-destroy from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.