
Env Discovery
- 1 installs
- 7 repo stars
- Updated July 30, 2026
- aws-samples/sample-aws-ops-skills-for-agents
env-discovery is a skill that discovers AWS account structure and fleet health by tag navigation using read-only calls, without enumerating individual resources.
About
env-discovery is a read-only AWS Fleet Intelligence skill that maps an account's structure by tag navigation instead of enumerating individual resources. A developer uses it to discover the tag taxonomy, aggregate resource counts by service tag, and check CloudWatch alarm status when onboarding to an account or answering what is running. It supports a global overview mode and a targeted drill-down mode into specific services.
- Discovers AWS environment structure by tag navigation without enumerating resources
- Aggregates resource counts by service tag and checks CloudWatch alarm status
- Purely read-only: all describe/list/get and resourcegroupstaggingapi calls
Env Discovery by the numbers
- 1 all-time installs (skills.sh)
- Ranked #933 of 1,039 Cloud & Infrastructure skills by installs in the Skillselion catalog
- Data as of Jul 31, 2026 (Skillselion catalog sync)
env-discovery capabilities & compatibility
- Capabilities
- aws discovery · fleet inventory · alarm status check
- Works with
- aws
- Use cases
- devops
What env-discovery says it does
Uses tag-based Fleet Intelligence: discovers tag taxonomy, aggregates resource counts by service tag, and checks alarm status — does NOT enumerate individual resources.
npx skills add https://github.com/aws-samples/sample-aws-ops-skills-for-agents --skill env-discoveryAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| repo stars | ★ 7 |
| Last updated | July 30, 2026 |
| Repository | aws-samples/sample-aws-ops-skills-for-agents ↗ |
What it does
Discover AWS account structure and fleet health by service tag using read-only calls.
Who is it for?
Engineers onboarding to a new AWS account or preparing an environment overview
Skip if: Enumerating or acting on individual resources, since it is read-only and tag-based
When should I use this skill?
Investigating what AWS services are running, checking fleet health by service tag, or onboarding to a new account
What you get
A tag-driven overview of services, resource counts, and current alarms for the account
- a terminal fleet summary
- updated account.yaml and account.md
- a per-service health and alarm overview
By the numbers
- three-phase scan: tag discovery, resource aggregation, alarm status
- two query modes
Files
Environment Discovery — Fleet Intelligence
通过 tag 导航发现环境结构,不枚举单个资源。
工作流程
1. 确认扫描目标
- 确认 account ID(默认
<account-id>,从 environment.md 读取) - 确认 region 范围(默认扫描 environment.md 中列出的所有 region)
2. 执行扫描
- 运行
scripts/discover-account.sh <account-id> <region> - 脚本三阶段独立执行:tag 发现 → 资源聚合 → 告警状态
- 输出 JSON 到 stdout,同时更新 environments/ 下的 account.yaml 和 account.md
3. 终端摘要输出
- 解析脚本输出的 JSON,渲染终端摘要
- 包含:各服务资源数量、当前告警、异常标记
- 报告中每条结论必须能追溯到本次扫描的 JSON 数据,禁止从 account.yaml 旧注释、历史报告、或记忆中搬运未验证信息
3.1 与上次扫描对比(可选)
- 读 account.yaml 获取上次 service_catalog,与本次 JSON 做 diff
- 对比范围仅限于本脚本覆盖的三个 phase(tag / 资源聚合 / 告警)
- account.yaml 中的注释、log_sources 等不在脚本扫描范围内的信息,不得作为对比结论引用——如需报告这些信息,必须单独查询验证
- 发现变化时标注「新增 / 消失 / 数量变化」,附具体数据
4. 两种查询模式
模式 1:全局概览("环境怎么样")
1. 读 environments/<account>/account.yaml 获取 service catalog 2. 查 CloudWatch Alarms in ALARM state → 按 alarm_prefix 归类到服务 3. 输出:各服务健康摘要 + 异常告警
模式 2:定向下钻("交易引擎的 DB 怎么样")
1. 从 service catalog 找到 tag 和 resource_types 2. 用 tag 过滤查询目标资源的 CloudWatch 指标
- RDS: CPUUtilization, FreeableMemory, ReplicaLag
- EC2: CPUUtilization, StatusCheckFailed
- EKS: pod restart count, node status
3. 只返回指标异常或用户关心的资源详情
查询参考
各服务具体的 AWS CLI 命令和解读要点见 references/service-checklist.md。 不要自行编写查询命令——用 checklist 中验证过的命令。
Automation Boundary
auto-safe
- 所有 describe / list / get 查询
- resourcegroupstaggingapi 调用
- cloudwatch describe-alarms
- 生成报告文件
human-required
- 无(本 skill 纯只读)
Gotchas
resourcegroupstaggingapi返回的 ARN 中ec2涵盖 instance/vpc/subnet/sg/nat/igw 等所有资源。必须从 ARN 第 6 段提取细分类型(如ec2:instance),否则会误报"19 台 EC2"实际是网络资源- Tag 推断 primary_key 时需排除 k8s 系统 tag(key 含
.或/的,如alpha.eksctl.io/xxx) - 个人/实验账号可能没有业务级 tag(如
service),Project或Name可能是最接近的替代 - account.yaml 中的历史注释不是实时数据。脚本只产出 tag/资源聚合/告警三类数据,account.yaml 中的
log_sources、手写注释等是其他流程或人工维护的。巡检报告不得把这些当作本次扫描结论。引用前必须用 CLI 验证当前状态 - 扫描后清理 account.yaml 中的过期注释。已解决的问题标注解决时间,未验证的问题不要留着——下次扫描会误导
环境报告:{account_id} / {region}
扫描时间:{timestamp}
扫描方式:Fleet Intelligence (tag-based aggregation)
数据来源:discover-account.sh Phase 1-3(tag / 资源聚合 / 告警)
Tag 体系
- 服务标识:
{primary_key} - 环境区分:
{environment_key} - 团队归属:
{owner_key}
服务摘要
| 服务 | 资源类型 | 资源数 | 告警状态 | 备注 |
|---|
{service_summary_rows}
与上次扫描对比
<!-- 仅对比脚本覆盖范围内的数据:Project tag 值、资源类型/数量、告警状态 -->
| 变化类型 | 详情 |
|---|
{diff_rows}
当前告警
{alarm_details}
本次发现的问题
<!-- 每条必须附数据来源:哪个 phase、哪个 region、具体数值 --> {anomalies}
需额外验证的项目
<!-- 脚本不覆盖的领域(log group、IAM、费用等),如需报告必须单独查询后填入 --> {needs_verification}
--- 报告由 env-discovery skill 自动生成。 规则:报告中每条结论必须可追溯到本次扫描数据。account.yaml 旧注释、历史报告中的信息不得直接引用——如需提及,先用 CLI 验证当前状态。
服务下钻查询 Checklist
以下命令用于"定向下钻"场景(模式 2),不用于全局扫描。
全局扫描走 discover-account.sh(tag 聚合),不走逐资源查询。
EKS
aws eks list-clusters --region {region}aws eks describe-cluster --name {name} --region {region}aws eks list-nodegroups --cluster-name {name} --region {region}- 关注:版本、节点组状态、endpoint 访问配置
- CloudWatch 指标:cluster 级 pod 数量、node CPU/Memory
Lambda
aws lambda list-functions --region {region}+ tag 过滤aws lambda get-function-configuration --function-name {name} --region {region}- 关注:runtime 版本、最近调用时间、内存配置、timeout
- CloudWatch 指标:Invocations, Errors, Duration, Throttles
ELBv2 (ALB/NLB)
aws elbv2 describe-load-balancers --region {region}+ tag 过滤aws elbv2 describe-target-groups --load-balancer-arn {arn} --region {region}aws elbv2 describe-target-health --target-group-arn {arn} --region {region}- 关注:target health 状态、unhealthy 数量、idle ALB
- CloudWatch 指标:RequestCount, TargetResponseTime, HTTPCode_Target_5XX
S3
aws s3api list-buckets(全局,不分 region)aws s3api get-bucket-encryption --bucket {name}aws s3api get-public-access-block --bucket {name}- 关注:加密状态、公开访问设置、versioning
- CloudWatch 指标:BucketSizeBytes, NumberOfObjects
RDS
aws rds describe-db-instances --region {region}+ tag 过滤aws rds describe-db-clusters --region {region}+ tag 过滤(Aurora)- 关注:引擎版本、Multi-AZ、备份配置、存储空间
- CloudWatch 指标:CPUUtilization, FreeableMemory, ReplicaLag, DatabaseConnections
ECR
aws ecr describe-repositories --region {region}aws ecr list-images --repository-name {name} --region {region} --filter tagStatus=UNTAGGED- 关注:镜像数量、lifecycle policy、untagged 镜像数
#!/usr/bin/env bash
# discover-account.sh — 轻量级账号资源发现(Fleet Intelligence)
#
# 用法:discover-account.sh <account-id> <region> [--output-dir <path>]
#
# 输出:
# stdout: JSON 格式的扫描结果(供 Claude 解析)
# 文件: account.yaml + account.md(写入 output-dir)
#
# 三个阶段独立执行,任一失败不影响其他:
# Phase 1: Tag 体系自动发现
# Phase 2: 按服务聚合资源计数
# Phase 3: 当前告警状态
set -euo pipefail
# ── 参数解析 ──────────────────────────────────────────────
ACCOUNT_ID="${1:-}"
REGION="${2:-}"
OUTPUT_DIR=""
shift 2 2>/dev/null || true
while [[ $# -gt 0 ]]; do
case "$1" in
--output-dir) OUTPUT_DIR="$2"; shift 2 ;;
--help|-h)
echo "用法: discover-account.sh <account-id> <region> [--output-dir <path>]"
echo ""
echo "轻量级 AWS 账号资源发现(Fleet Intelligence)"
echo "通过 tag 聚合发现环境结构,不枚举单个资源。"
echo ""
echo "参数:"
echo " account-id AWS 账号 ID"
echo " region AWS Region(如 ap-northeast-1)"
echo " --output-dir 输出目录(默认: environments/<account-id>/)"
exit 0
;;
*) echo "未知参数: $1" >&2; exit 1 ;;
esac
done
if [[ -z "$ACCOUNT_ID" || -z "$REGION" ]]; then
echo "错误: 必须提供 account-id 和 region" >&2
echo "用法: discover-account.sh <account-id> <region> [--output-dir <path>]" >&2
exit 1
fi
# 定位 repo 根目录
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../../../../.." && pwd)"
if [[ -z "$OUTPUT_DIR" ]]; then
OUTPUT_DIR="$REPO_ROOT/environments/$ACCOUNT_ID"
fi
mkdir -p "$OUTPUT_DIR/regions" "$OUTPUT_DIR/services"
# JSON 输出累积
RESULT_JSON="{}"
# ── 辅助函数 ──────────────────────────────────────────────
log() { echo "[discover] $*" >&2; }
# ── Phase 1: Tag 体系自动发现 ─────────────────────────────
phase1_discover_tags() {
log "Phase 1: 发现 tag 体系..."
# 获取所有 tag key
local tag_keys
tag_keys=$(aws resourcegroupstaggingapi get-tag-keys \
--region "$REGION" \
--output json 2>/dev/null) || {
log "Phase 1 失败: 无法获取 tag keys(可能缺少权限)"
echo '{"phase1": {"status": "error", "message": "get-tag-keys failed"}}'
return 1
}
# 提取 key 列表(排除 aws: 开头的系统 tag)
local keys
keys=$(echo "$tag_keys" | jq -r '.TagKeys[] | select(startswith("aws:") | not)')
if [[ -z "$keys" ]]; then
log "Phase 1: 未发现用户自定义 tag"
echo '{"phase1": {"status": "empty", "tag_keys": []}}'
return 0
fi
# 对每个 key 只获取值(不调 get-resources,避免大账号慢查询)
local tag_analysis="[]"
while IFS= read -r key; do
local values
values=$(aws resourcegroupstaggingapi get-tag-values \
--region "$REGION" \
--key "$key" \
--output json 2>/dev/null) || continue
local value_count
value_count=$(echo "$values" | jq '.TagValues | length')
tag_analysis=$(echo "$tag_analysis" | jq \
--arg key "$key" \
--argjson vc "$value_count" \
--argjson vals "$(echo "$values" | jq '.TagValues')" \
'. + [{"key": $key, "value_count": $vc, "values": $vals}]')
done <<< "$keys"
# 推断 tag 角色(纯基于 key 名称 + value 模式,不查资源数量)
local primary_key=""
local env_key=""
local owner_key=""
# environment_key: 值包含 prod/staging/dev
env_key=$(echo "$tag_analysis" | jq -r '
[.[] | select(.values | map(ascii_downcase) | any(. == "prod" or . == "production" or . == "staging" or . == "dev" or . == "development"))]
| .[0].key // ""')
# owner_key: key 名包含 owner/team/squad
owner_key=$(echo "$tag_analysis" | jq -r '
[.[] | select(.key | ascii_downcase | test("owner|team|squad|group"))]
| .[0].key // ""')
# primary_key: 排除已识别的 env/owner key 后,值基数 2-50 且 key 名
# 像 service/application/component/app/project 的优先
# 排除 k8s 系统 tag(含 . 或 / 的 key,如 alpha.eksctl.io/xxx)
primary_key=$(echo "$tag_analysis" | jq -r \
--arg ek "$env_key" \
--arg ok "$owner_key" '
[.[] | select(
.key != $ek and .key != $ok
and .value_count >= 2 and .value_count <= 50
and (.key | test("[./]") | not)
)]
| sort_by(
if .key | ascii_downcase | test("^(service|application|component|app|project)$") then 0
elif .key | ascii_downcase | test("service|application|component|app|project") then 1
else 2 end
)
| .[0].key // ""')
local phase1_result
phase1_result=$(jq -n \
--arg pk "$primary_key" \
--arg ek "$env_key" \
--arg ok "$owner_key" \
--argjson analysis "$tag_analysis" \
'{
"phase1": {
"status": "ok",
"inferred_strategy": {
"primary_key": $pk,
"environment_key": $ek,
"owner_key": $ok
},
"tag_analysis": $analysis
}
}')
echo "$phase1_result"
log "Phase 1 完成: primary=$primary_key, env=$env_key, owner=$owner_key"
}
# ── Phase 2: 按服务聚合资源计数 ───────────────────────────
phase2_aggregate_resources() {
local primary_key="$1"
log "Phase 2: 按 $primary_key 聚合资源..."
if [[ -z "$primary_key" ]]; then
log "Phase 2 跳过: 无 primary_key"
echo '{"phase2": {"status": "skipped", "message": "no primary_key"}}'
return 0
fi
# 获取 primary tag 的所有值(即服务列表)
local services
services=$(aws resourcegroupstaggingapi get-tag-values \
--region "$REGION" \
--key "$primary_key" \
--output json 2>/dev/null | jq -r '.TagValues[]') || {
log "Phase 2 失败: 无法获取 $primary_key 的值"
echo '{"phase2": {"status": "error"}}'
return 1
}
local catalog="{}"
while IFS= read -r service; do
[[ -z "$service" ]] && continue
# 获取该服务下所有资源,按类型统计
local resources
resources=$(aws resourcegroupstaggingapi get-resources \
--region "$REGION" \
--tag-filters "Key=$primary_key,Values=$service" \
--output json 2>/dev/null) || continue
# 按 resource type 聚合计数
# ARN 格式: arn:aws:SERVICE:region:account:RESOURCE-TYPE/id
# 从 ARN 提取有意义的资源类型(如 ec2:instance、ec2:vpc、rds:cluster)
local counts
counts=$(echo "$resources" | jq '
.ResourceTagMappingList
| map(.ResourceARN | split(":") |
if .[5] | contains("/") then
.[2] + ":" + (.[5] | split("/") | .[0])
else
.[2] + ":" + .[5]
end
)
| group_by(.)
| map({(.[0]): length})
| add // {}')
catalog=$(echo "$catalog" | jq \
--arg svc "$service" \
--argjson counts "$counts" \
'. + {($svc): {"resource_counts": $counts}}')
done <<< "$services"
local phase2_result
phase2_result=$(jq -n --argjson catalog "$catalog" '{"phase2": {"status": "ok", "service_catalog": $catalog}}')
echo "$phase2_result"
log "Phase 2 完成: $(echo "$catalog" | jq 'keys | length') 个服务"
}
# ── Phase 3: 当前告警状态 ─────────────────────────────────
phase3_alarm_status() {
log "Phase 3: 查询告警状态..."
local alarms_alarm
alarms_alarm=$(aws cloudwatch describe-alarms \
--region "$REGION" \
--state-value ALARM \
--output json 2>/dev/null | jq '[.MetricAlarms[] | {name: .AlarmName, state: "ALARM", metric: .MetricName, namespace: .Namespace}]') || alarms_alarm="[]"
local alarms_insufficient
alarms_insufficient=$(aws cloudwatch describe-alarms \
--region "$REGION" \
--state-value INSUFFICIENT_DATA \
--output json 2>/dev/null | jq '[.MetricAlarms[] | {name: .AlarmName, state: "INSUFFICIENT_DATA", metric: .MetricName, namespace: .Namespace}]') || alarms_insufficient="[]"
local all_alarms
all_alarms=$(jq -n --argjson a "$alarms_alarm" --argjson i "$alarms_insufficient" '$a + $i')
local alarm_count
alarm_count=$(echo "$alarms_alarm" | jq 'length')
local insufficient_count
insufficient_count=$(echo "$alarms_insufficient" | jq 'length')
local phase3_result
phase3_result=$(jq -n \
--argjson alarms "$all_alarms" \
--argjson ac "$alarm_count" \
--argjson ic "$insufficient_count" \
'{
"phase3": {
"status": "ok",
"alarm_count": $ac,
"insufficient_data_count": $ic,
"alarms": $alarms
}
}')
echo "$phase3_result"
log "Phase 3 完成: $alarm_count ALARM, $insufficient_count INSUFFICIENT_DATA"
}
# ── 派生视图:跨 region 账号索引 ──────────────────────────
regenerate_account_view() {
local regions_dir="$OUTPUT_DIR/regions"
local account_md="$OUTPUT_DIR/account.md"
local json_files=("$regions_dir"/*.json)
[[ ! -e "${json_files[0]}" ]] && return
local all
all=$(jq -s '.' "${json_files[@]}")
{
echo "# 账号概览:$ACCOUNT_ID"
echo ""
echo "> Fleet Intelligence — 跨 region 索引(派生自 regions/*.json)"
echo ""
echo "## 扫描状态"
echo "| Region | 最近扫描 | 服务数 | ALARM | INSUFFICIENT_DATA |"
echo "|--------|----------|--------|-------|-------------------|"
echo "$all" | jq -r '.[] | "| \(.region) | \(.timestamp) | \(.phases.phase2.service_catalog // {} | length) | \(.phases.phase3.alarm_count // 0) | \(.phases.phase3.insufficient_data_count // 0) |"'
echo ""
echo "## Tag 体系"
echo "$all" | jq -r '[.[] | .phases.phase1.inferred_strategy] | .[0] // {} | "- 服务标识:`\(.primary_key // "")`\n- 环境区分:`\(.environment_key // "")`\n- 团队归属:`\(.owner_key // "")`"'
echo ""
echo "## 服务分布"
echo "| 服务 | Region |"
echo "|------|--------|"
echo "$all" | jq -r '
[.[] | .region as $r | (.phases.phase2.service_catalog // {} | keys) | map({service: ., region: $r})] | flatten
| group_by(.service)
| map({service: .[0].service, regions: (map(.region) | sort | join(", "))})
| sort_by(.service)
| .[] | "| \(.service) | \(.regions) |"
'
echo ""
echo "## 当前告警"
local alarms
alarms=$(echo "$all" | jq -r '
[.[] | .region as $r | (.phases.phase3.alarms // []) | map(. + {region: $r})] | flatten
| .[] | "- **\(.state)** [\(.region)]: \(.name) (\(.metric) / \(.namespace))"
')
if [[ -z "$alarms" ]]; then
echo "- 无告警"
else
echo "$alarms"
fi
} > "$account_md"
}
# ── 派生视图:按服务聚合(跨 region)──────────────────────
regenerate_services_view() {
local regions_dir="$OUTPUT_DIR/regions"
local services_dir="$OUTPUT_DIR/services"
local json_files=("$regions_dir"/*.json)
[[ ! -e "${json_files[0]}" ]] && return
mkdir -p "$services_dir"
rm -f "$services_dir"/*.md
local all
all=$(jq -s '.' "${json_files[@]}")
local services
services=$(echo "$all" | jq -r '[.[] | .phases.phase2.service_catalog // {} | keys] | flatten | unique | .[]')
while IFS= read -r svc; do
[[ -z "$svc" ]] && continue
local svc_md="$services_dir/$svc.md"
{
echo "# 服务:$svc"
echo ""
echo "> Fleet Intelligence — 按服务汇总(派生自 regions/*.json)"
echo ""
echo "$all" | jq -r --arg s "$svc" '
.[] | select(.phases.phase2.service_catalog[$s]) |
"## \(.region)\n\n> 扫描时间:\(.timestamp)\n\n| 资源类型 | 数量 |\n|----------|------|\n" +
(.phases.phase2.service_catalog[$s].resource_counts | to_entries | map("| \(.key) | \(.value) |") | join("\n")) + "\n"
'
} > "$svc_md"
done <<< "$services"
}
# ── 主流程 ────────────────────────────────────────────────
main() {
log "开始扫描 Account=$ACCOUNT_ID Region=$REGION"
# 验证身份
local caller
caller=$(aws sts get-caller-identity --output json 2>/dev/null) || {
echo '{"error": "无法验证 AWS 身份,请检查凭证配置"}' >&2
exit 1
}
local actual_account
actual_account=$(echo "$caller" | jq -r '.Account')
if [[ "$actual_account" != "$ACCOUNT_ID" ]]; then
log "警告: 当前凭证账号 $actual_account 与目标 $ACCOUNT_ID 不匹配"
fi
# Phase 1
local p1_result
p1_result=$(phase1_discover_tags) || p1_result='{"phase1":{"status":"error"}}'
# 提取 primary_key 供 Phase 2 使用
local primary_key
primary_key=$(echo "$p1_result" | jq -r '.phase1.inferred_strategy.primary_key // ""')
# Phase 2
local p2_result
p2_result=$(phase2_aggregate_resources "$primary_key") || p2_result='{"phase2":{"status":"error"}}'
# Phase 3
local p3_result
p3_result=$(phase3_alarm_status) || p3_result='{"phase3":{"status":"error"}}'
# 合并结果
local timestamp
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
local combined
combined=$(jq -n \
--arg account "$ACCOUNT_ID" \
--arg region "$REGION" \
--arg ts "$timestamp" \
--argjson p1 "$p1_result" \
--argjson p2 "$p2_result" \
--argjson p3 "$p3_result" \
'{
account_id: $account,
region: $region,
timestamp: $ts,
phases: ($p1 + $p2 + $p3)
}')
# 写入 per-region source of truth
local region_json_file="$OUTPUT_DIR/regions/$REGION.json"
local region_md_file="$OUTPUT_DIR/regions/$REGION.md"
echo "$combined" | jq '.' > "$region_json_file"
local env_key
env_key=$(echo "$p1_result" | jq -r '.phase1.inferred_strategy.environment_key // ""')
local owner_key
owner_key=$(echo "$p1_result" | jq -r '.phase1.inferred_strategy.owner_key // ""')
local svc_table
svc_table=$(echo "$p2_result" | jq -r '
.phase2.service_catalog // {} | to_entries[] |
"| \(.key) | \(.value.resource_counts | to_entries | map("\(.key):\(.value)") | join(", ")) |"
' 2>/dev/null)
[[ -z "$svc_table" ]] && svc_table="| (未发现) | — |"
local alarm_section
alarm_section=$(echo "$p3_result" | jq -r '
.phase3.alarms // [] | .[] |
"- **\(.state)**: \(.name) (\(.metric) / \(.namespace))"
' 2>/dev/null)
[[ -z "$alarm_section" ]] && alarm_section="- 无告警"
cat > "$region_md_file" <<MD
# Region: $REGION ($ACCOUNT_ID)
> 扫描时间:$timestamp
> 扫描方式:Fleet Intelligence (tag-based aggregation)
## Tag 体系
- 服务标识:\`$primary_key\`
- 环境区分:\`$env_key\`
- 团队归属:\`$owner_key\`
## 服务目录
| 服务 | 资源 |
|------|------|
$svc_table
## 当前告警
$alarm_section
MD
# 从所有 regions/*.json 重建派生视图
regenerate_account_view
regenerate_services_view
# stdout 输出 JSON
echo "$combined"
log "完成。报告写入 $OUTPUT_DIR/regions/$REGION.{json,md},派生视图已重建"
}
main
Related skills
FAQ
Does env-discovery change anything?
No. It is purely read-only; all describe, list, get, and resourcegroupstaggingapi calls are auto-safe and there are no human-required mutations.
Does it enumerate every resource?
No. It navigates by tag and aggregates counts by service tag rather than enumerating individual resources.