From arn-infra
Checks TTL sources (issue tracker, registry, manifest) for expired ephemeral infrastructure resources and destroys them after user confirmation with cost summary. Supports /loop for periodic monitoring.
How this skill is triggered — by the user, by Claude, or both
Slash command
/arn-infra:arn-infra-cleanupThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Check for expired ephemeral infrastructure resources across three TTL sources (issue tracker, TTL registry, resource manifest) and destroy them with user confirmation. Supports periodic monitoring via `/loop` for session-duration TTL enforcement.
Check for expired ephemeral infrastructure resources across three TTL sources (issue tracker, TTL registry, resource manifest) and destroy them with user confirmation. Supports periodic monitoring via /loop for session-duration TTL enforcement.
This skill never auto-destroys resources. Every destruction requires explicit user confirmation with a summary of what will be destroyed and its associated cost.
Read ## Arness from the project's CLAUDE.md. If no ## Arness section exists or Arness Infra fields are missing, inform the user: "Arness Infra is not configured for this project yet. Run /arn-infra-wizard to get started — it will set everything up automatically." Do not proceed without it.
Check the Deferred field. If Deferred: yes, inform the user: "Infrastructure is in deferred mode. Cleanup is not available until infrastructure is fully configured. Run /arn-infra-assess to un-defer." Stop.
Extract:
~/.arness/user-profile.yaml (or .claude/arness-profile.local.md if it exists — project override takes precedence). Apply the experience derivation mapping from ${CLAUDE_PLUGIN_ROOT}/skills/arn-infra-ensure-config/references/experience-derivation.md. If no profile exists, check for legacy Experience level in ## Arness as fallback.providers.mdenvironments.md for per-environment deployment stateactive-resources.json for resource inventorytooling-manifest.json for available CLIsCheck all three TTL sources in priority order. Collect a unified list of resources with expired or near-expiry TTLs.
Source 1: Issue Tracker (highest priority)
If issue tracking is configured (Platform is github or Issue tracker is jira):
For GitHub:
gh issue list --label "arn-infra-cleanup" --state open --json number,title,body,createdAt
For Jira:
Query issues with label arn-infra-cleanup in the configured Jira project.
Parse each cleanup issue:
arn-infra-deploy during ephemeral deployments)Source 2: TTL Registry (secondary)
Check for the TTL registry file:
Read .arness/infra/ttl-registry.md
If the file exists, parse resource entries with their TTL timestamps. The TTL registry is a fallback for environments without issue tracking or for resources created outside the normal deployment flow.
Expected format:
# TTL Registry
| Resource | Environment | Provider | Created | TTL Expiry | Destroy Command |
|----------|-------------|----------|---------|------------|-----------------|
| [name] | [env] | [provider] | [timestamp] | [expiry] | [command] |
Source 3: Resource Manifest (tertiary)
Read the resource manifest:
Read <resource-manifest-path>
Filter resources where:
ttl is not nullttl timestamp is in the past (expired)status is active (not already destroyed)Merge results from all three sources, deduplicating by resource ID. For each expired resource, compile:
monthly_cost × (hours_since_creation / 730))If no expired resources are found:
Present: "No expired resources found. All TTLs are current."
If there are resources with TTLs approaching expiry (within 1 hour), list them as early warnings: "The following resources will expire soon:
Stop here (or if running via /loop, wait for the next interval).
If expired resources are found:
Continue to Step 3.
Present each expired resource group (grouped by environment):
"The following resources have expired TTLs and are candidates for cleanup:
Environment: [env]
| Resource | Type | Provider | Expired | Cost Since Creation | Destroy Command |
|---|---|---|---|---|---|
| [name] | [type] | [provider] | [time since expiry] | $[amount] | [command] |
Total cost of expired resources: $[total] (estimated charges since TTL expired)
Ask (using AskUserQuestion):
"How would you like to handle the expired resources?"
Options:
NEVER auto-destroy without confirmation. Even when running via /loop, each cleanup cycle must ask for confirmation before destroying anything.
For each confirmed resource, execute the appropriate destroy command.
Read the local override or plugin default for
rollback-patterns.md.
Destroy commands by IaC tool:
| IaC Tool | Destroy Command |
|---|---|
| OpenTofu | tofu destroy -target=<resource> -var-file=environments/<env>.tfvars |
| Terraform | terraform destroy -target=<resource> -var-file=environments/<env>.tfvars |
| Pulumi | pulumi destroy --target <urn> --stack <env> --yes |
| CDK | cdk destroy --context env=<env> |
| Bicep | az resource delete --ids <resource-id> |
| kubectl | kubectl delete <resource-type> <name> -n <namespace> |
| Helm | helm uninstall <release> -n <namespace> |
| Fly.io | fly apps destroy <app-name> --yes |
| Railway | railway down or delete via dashboard |
| Vercel | vercel remove <project> --yes |
| Netlify | netlify sites:delete --id <site-id> |
| Render | Delete via Render dashboard |
For targeted IaC destruction (OpenTofu/Terraform):
When destroying specific resources from a larger state file, use -target to avoid destroying the entire environment:
tofu destroy -target=module.<module>.<resource_type>.<name> -var-file=environments/<env>.tfvars
For full environment teardown: If all resources in an environment are expired, offer full environment destruction:
tofu destroy -var-file=environments/<env>.tfvars
Important: Always ask for confirmation before executing destroy commands. Show the exact command that will be run.
After successful destruction:
5a. Update resource manifest:
status to destroyed for each destroyed resourcelastUpdated timestamp5b. Close/update cleanup issues: If the resource was tracked via an issue:
gh issue close <number> --comment "Resources destroyed by arn-infra-cleanup at [timestamp]."
5c. Update TTL registry:
If the resource was tracked in .arness/infra/ttl-registry.md, remove the entry or mark it as destroyed.
5d. Update Environments config: If all resources in an environment were destroyed (read from the Environments config path extracted in Prerequisites):
Last deployed: --, Pending changes: noneIf the user chose to extend TTL for some resources:
Ask: "How long would you like to extend the TTL? (e.g., 2h, 24h, 7d)"
For each selected resource:
ttl field in active-resources.jsonPresent: "TTL extended for [N] resources. New expiry: [timestamp]. The next cleanup check will re-evaluate these resources."
Present the cleanup summary:
"Cleanup Summary:
Files updated:
Remaining TTLs:
Periodic monitoring:
To automatically check for expired resources, use:
/loop 6h /arn-infra-cleanup
This will check TTLs every 6 hours during the current session and prompt for cleanup when resources expire."
This skill supports periodic execution via the /loop command:
/loop 6h /arn-infra-cleanup
When running in loop mode:
Recommended loop intervals:
## Arness config missing: Suggest running /arn-infra-wizard to get started. Stop./arn-infra-deploy (which creates cleanup issues) or manually add resources to .arness/infra/ttl-registry.md." Stop.destroyed in the manifest and close any associated cleanup issue. Inform the user: "[resource] was already destroyed (possibly manually or by another process)."destroyed in manifest). Closed issues are filtered out by the open-issues query.npx claudepluginhub appsvortex/arness --plugin arn-infraEnforces cloud operational hygiene: resource cleanup after migrations, cost attribution/tagging, monitoring/alerting defaults, Terraform drift detection, lifecycle policies for storage/artifacts.
Deploys infrastructure to staging or production using Terraform, Pulumi, CDK, Fly, or Railway. Enforces environment promotion, CI/CD checks, cost gates, safety layers, and resource tracking.
Automates dry-run cleanup of unused AWS resources like unattached EBS volumes, old snapshots, stopped EC2 instances, Elastic IPs, and S3 objects to reduce costs.