目次

1.はじめに
2.aws-unused-resource-searcher Skillの作成
3.aws-unused-resource-searcher Skillの実行
4.おわりに

1.はじめに

Gemini CLI の組み込み skill-creator とは Gemini CLI 上での Agent Skills 作成を支援してくれる機能です。
Gemini CLI の v0.26.0(安定版)でリリースされました。 

Agent Skills 自体は Gemini CLI の v0.24.0(安定版)で使えるようになったのですが、ユーザーが手動で Skill 用ディレクトリや設定ファイルを作成する必要がありました。
skill-creator が Gemini CLI に組み込まれたことで、Gemini CLI 上でのやり取りベースで Skill 用ディレクトリや設定ファイルの生成ができます。

本ブログは Claude CodeとGemini CLIでAgent Skillsを使ってみた の内容をもとにします。
上記のブログでは、Claude Code に skill-creator をインストールし、その skill-creator を使って Skill を作成、Gemini CLI で流用する形をとっていました。

本ブログでは Claude Code で Skill を作成した時と同じプロンプトを Gemini CLI の組み込み skill-creator を使う形で実行し、どのような Skill が作成されるかを試してみます。

2.aws-unused-resource-searcher Skillの作成

動作環境や利用モデル、事前準備については以下の通りです。

動作環境

  • macOS:Sequoia 15.7.3
  • Node.js のバージョン( node --version ):24.11.1
  • Gemini CLI のバージョン( gemini --version ):0.26.0

利用モデル

  • 利用モデル:Gemini 3 を含んだ Auto モード

事前準備

上記設定の上、Gemini CLI を立ち上げ、Skill を作成していきます。

組み込みskill-creatorを使ってのSkill作成

Gemini CLI を立ち上げ、組み込み skill-creator を使ってみます。
まず、設定を確認しておきます。

Agent Skills は有効状態です。

以下のプロンプトを実行します。
こちらのブログで実行したプロンプトと同じ内容で、AWS アカウント内のリソース使用実態有無を調査するための Skill を作成します)

skill-creator name--name aws-unused-resource-searcher --description "AWS 
アカウント内のリソース利用状況を分析し、一定期間アクティビティが確認されない EC2、EBS、NAT Gateway、ALB、NLB 
などの未使用リソース候補を検出する。CloudWatch メトリクスおよび AWS API 情報を用いて、削除可能性を一覧で出力する。"

skill-creator が 起動し、Skill の作成に進みます。

✓  Activate Skill "skill-creator": Guide for creating effective skills. This skill should be used when users want to create a new skill

skill-creator の起動後、まずは Skill の初期化が実行されます。
init_skill.cjs スクリプトを使用し、標準的なディレクトリ構造(scripts/, references/, assets/)と設定ファイルが生成されます。

続いて、AWS の未使用リソースを特定するためのリソース検出スクリプト(scripts/find_unused_resources.py)が生成されます。

私のローカル環境では boto3 が利用可能だったため、Python のスクリプトが生成されました。
スクリプトは以下のロジックを含む内容となっています。

  • EC2: 停止中のもの、または過去7日間の平均 CPU 使用率が1%未満のものを検出。
  • EBS: どのインスタンスにもアタッチされていない「Available」状態のボリュームを検出。
  • Elastic IP: インスタンスやネットワークインターフェースに関連付けられていない IP を検出。

続いて、スクリプトを直接実行できるよう、実行権限 (chmod +x) を付与。
次に SKILL.md の編集が行われます。

SKILL.md の編集内容としては、「いつ、どのように使われるべきか」がわかるよう、日本語の description を記述の上、スクリプトの実行方法や、AWS 環境に対し、どのようなチェックが行われるかの詳細が記述されました。

続いて、クリーンアップの実行として、初期化時に作成したが、不要となったファイルが削除されます。

続いて、作成したディレクトリ、設定ファイルを .skill という拡張子のアーカイブファイルにパッケージ化するという処理が実行されます。

これで Skill の実行に必要な SKILL.md と、今回の場合ですと Python のスクリプトが作成されました。
その流れで作成された Skill を現在使用中のディレクトリか、それともグローバルに使用できる形とするかを問われます。

  このスキルをインストールしますか?
  ご希望のインストール範囲をお知らせください:

   1. ワークスペース (Workspace): このディレクトリでの作業時のみ有効
   2. ユーザー (User): どこでも使用可能 (推奨)

> 2. ユーザー (User): どこでも使用可能 (推奨)としてください
✦ I will now install the aws-unused-resource-searcher skill to the user scope.
 1 gemini skills install aws-unused-resource-searcher.skill --scope user
〜〜省略〜〜
The following agent skill(s) will be installed:                                                                                       │
│                                                                                                                                       │
│   * aws-unused-resource-searcher: AWS アカウント内のリソース利用状況を分析し、一定期間アクティビティが確認されない EC2、EBS、NAT      │
│ Gateway、ALB、NLB などの 未使用リソース候補を検出する。CloudWatch メトリクスおよび AWS API 情報を用いて、削除可能性を一覧で出力する。
〜〜省略〜〜
Install Destination: /Users/名前/.gemini/skills 
Agent skills inject specialized instructions and domain-specific knowledge into the agent's system prompt. This can change how the    │
│ agent interprets your requests and interacts with your environment. Review the skill definitions at the location(s) provided below to │
│ ensure they meet your security standards.                                                                                             │
│ Do you want to continue? [Y/n]: Y                                                                                                     │
│ Successfully installed skill: aws-unused-resource-searcher (scope: user, location:                                                    │
│ /Users/名前/.gemini/skills/aws-unused-resource-searcher)  

Skill をグローバルに使用できる形としました。
これで Skill の完成です。

Skill の reload コマンドを実行します。

reload コマンド実行後、list コマンドで今回作成した Skill が表示されることが確認できました。

Skill の作成と設定はこれで以上です。

実際に作成した Skill を動かす前に、作成されたディレクトリと SKILL.md、Python のスクリプトを見てみます。
Gemini CLI を立ち上げた作業ディレクトリに Skill 名のディレクトリ、SKILL.md、Python のスクリプトが作成されています。
拡張子 .skill のものは作成したディレクトリをパッケージ化したものです。

csk/ # 作業ディレクトリ
├── aws-unused-resource-searcher/ # AWS 未使用リソース検出 Agent Skills の定義を格納するディレクトリ
│   ├── scripts/ # リソース検出に使用するスクリプトを格納するディレクトリ
│   │   └── find_unused_resources.py # EC2、EBS、Elastic IP の未使用リソースを検出する Python スクリプト
│   └── SKILL.md # このSkillの使用方法、前提条件、チェック内容を記載したドキュメント
└── aws-unused-resource-searcher.skill # この Agent Skills をパッケージ化

.gemini にも Skill 用のディレクトリと設定ファイルが存在します。
Skill の使用範囲として、グローバルで使用可能とする形としたので、.gemini フォルダに skills フォルダが作成され、その中に Skill 名のディレクトリと SKILL.md、Python のスクリプトが格納されています。

.gemini/
└── skills/ # Agent Skillsを格納するディレクトリ
    └── aws-unused-resource-searcher/ # AWS 未使用リソース検出 Agent Skills の定義を格納するディレクトリ
        ├── scripts/ # リソース検出に使用するスクリプトを格納するディレクトリ
        │   └── find_unused_resources.py # EC2、EBS、Elastic IP の未使用リソースを検出する Python スクリプト
        └── SKILL.md # このSkillの使用方法、前提条件、チェック内容を記載したドキュメント

次に作成された設定ファイルを見ていきます。

SKILL.mdとスクリプトの確認

SKILL.md については、

  • AWS アカウント内をスキャン。EC2・EBS・EIP などの使われていない可能性が高いリソースを検出しコスト削減の判断材料を出すこと。
  • Python スクリプトを実行し、CloudWatch メトリクス(CPU 使用率など)と AWS API 情報を使って、一定期間アクティビティがないリソースを洗い出すこと。
  • 停止中の EC2 インスタンス、CPU 使用率が極めて低い実行中インスタンス、未アタッチの EBS ボリューム、未割り当ての Elastic IPs など複数の判定基準でリソースを評価すること。

が定義されています。

SKILL.md
---
name: aws-unused-resource-searcher
description: AWS アカウント内のリソース利用状況を分析し、一定期間アクティビティが確認されない EC2、EBS、NAT Gateway、ALB、NLB などの未使用リソース候補を検出する。CloudWatch メトリクスおよび AWS API 情報を用いて、削除可能性を一覧で出力する。
---

# AWS Unused Resource Searcher

## Overview

This skill helps identify potentially unused AWS resources in a specific region to assist with cost optimization. It uses a bundled Python script to scan for resources that show signs of inactivity.

## Usage

To use this skill, run the provided script `scripts/find_unused_resources.py`.

### Prerequisites
- AWS Credentials configured in the environment (e.g., via `~/.aws/credentials` or environment variables).
- Python 3 with `boto3` installed.

### Command

# Run the scanner for a specific region (e.g., us-east-1)
./aws-unused-resource-searcher/scripts/find_unused_resources.py --region <region_name>

## Resource Checks

The script performs the following checks:

### 1. EC2 Instances
- **Stopped Instances**: Lists any instance currently in the 'stopped' state.
- **Low CPU Utilization**: Lists 'running' instances with average CPU utilization < 1% over the last 7 days.

### 2. EBS Volumes
- **Unattached Volumes**: Lists any volume with status 'available' (not attached to any instance).

### 3. Elastic IPs (EIP)
- **Unassociated IPs**: Lists Elastic IPs that are not associated with any instance or network interface.

## Next Steps

After identifying unused resources:
1.  **Verify**: Manually verify if the resource is indeed not needed (e.g., it might be a cold standby).
2.  **Snapshot**: Consider creating a snapshot of EBS volumes before deletion.
3.  **Delete/Release**: Remove the resources to save costs.

find_unused_resources.py については、指定した AWS リージョンに対し、EC2 インスタンス・EBS ボリューム・Elastic IP を対象に「未使用の可能性があるリソース」を洗い出すことを定義した内容となっています。


find_unused_resources.py

#!/usr/bin/env python3
import boto3
import argparse
import sys
from datetime import datetime, timedelta

def get_boto3_client(service, region):
    return boto3.client(service, region_name=region)

def check_ec2_instances(region):
    print(f"--- Checking EC2 Instances in {region} ---")
    ec2 = get_boto3_client('ec2', region)
    cw = get_boto3_client('cloudwatch', region)

    try:
        response = ec2.describe_instances(Filters=[{'Name': 'instance-state-name', 'Values': ['running', 'stopped']}])
        instances = []
        for r in response['Reservations']:
            instances.extend(r['Instances'])

        unused_instances = []

        for i in instances:
            instance_id = i['InstanceId']
            state = i['State']['Name']
            name = next((t['Value'] for t in i.get('Tags', []) if t['Key'] == 'Name'), instance_id)

            if state == 'stopped':
                unused_instances.append(f"[STOPPED] {name} ({instance_id}) is stopped.")
            elif state == 'running':
                # Check CPU utilization for the last 7 days
                end_time = datetime.utcnow()
                start_time = end_time - timedelta(days=7)

                try:
                    metrics = cw.get_metric_statistics(
                        Namespace='AWS/EC2',
                        MetricName='CPUUtilization',
                        Dimensions=[{'Name': 'InstanceId', 'Value': instance_id}],
                        StartTime=start_time,
                        EndTime=end_time,
                        Period=86400, # 1 day
                        Statistics=['Average']
                    )

                    if metrics['Datapoints']:
                        avg_cpu = sum([d['Average'] for d in metrics['Datapoints']]) / len(metrics['Datapoints'])
                        if avg_cpu < 1.0:
                             unused_instances.append(f"[LOW CPU] {name} ({instance_id}) has < 1% avg CPU over 7 days ({avg_cpu:.2f}%).")
                    else:
                         # No data often means it hasn't been running long or monitoring is off
                         pass 
                except Exception as e:
                    print(f"  Warning: Could not get metrics for {instance_id}: {e}")

        if unused_instances:
            for item in unused_instances:
                print(item)
        else:
            print("No clearly unused EC2 instances found.")

    except Exception as e:
        print(f"Error checking EC2 instances: {e}")

def check_ebs_volumes(region):
    print(f"\n--- Checking EBS Volumes in {region} ---")
    ec2 = get_boto3_client('ec2', region)

    try:
        response = ec2.describe_volumes(Filters=[{'Name': 'status', 'Values': ['available']}])
        volumes = response['Volumes']

        if volumes:
            for v in volumes:
                vol_id = v['VolumeId']
                size = v['Size']
                created = v['CreateTime'].strftime('%Y-%m-%d')
                print(f"[UNATTACHED] {vol_id} ({size} GiB) created on {created} is available.")
        else:
            print("No unattached EBS volumes found.")

    except Exception as e:
        print(f"Error checking EBS volumes: {e}")

def check_eips(region):
    print(f"\n--- Checking Elastic IPs in {region} ---")
    ec2 = get_boto3_client('ec2', region)

    try:
        response = ec2.describe_addresses()
        eips = response['Addresses']

        found = False
        for eip in eips:
            if 'AssociationId' not in eip:
                print(f"[UNASSOCIATED] {eip['PublicIp']} is not associated with any resource.")
                found = True

        if not found:
            print("No unassociated Elastic IPs found.")

    except Exception as e:
        print(f"Error checking Elastic IPs: {e}")

def main():
    parser = argparse.ArgumentParser(description="Find unused AWS resources.")
    parser.add_argument("--region", type=str, required=True, help="AWS Region to check")
    args = parser.parse_args()

    print(f"Scanning for unused resources in region: {args.region}\n")

    check_ec2_instances(args.region)
    check_ebs_volumes(args.region)
    check_eips(args.region)

    print("\nScan complete.")

if __name__ == "__main__":
    main()

SKILL.md と find_unused_resources.py の内容についてですが、そもそもの skill-creator 実行時の要望は、EC2、EBS、NAT Gateway、ALB、NLB などの未使用リソース候補を検出~ することです。

SKILL.md の description では~ EC2、EBS、NAT Gateway、ALB、NLB などの未使用リソース候補を検出する~と定義されていますが、SKILL.md の内容とスクリプトは EC2、EBS、Elastic IP への具体的言及に留まっています。
本来なら、少なくとも NAT Gateway、ALB、NLB にも具体的言及をするよう、SKILL.md や スクリプトの編集指示を出すべきですが、今回はこのままで Skill を実行してみます。

3.aws-unused-resource-searcher Skillの実行

作成した Skill は AWS アカウント内の不要リソース有無調査の機能を定義したものなので、あらかじめAWSリソースを作成しておきます。
こちらのブログと同様、以下のリソースを作成しました。

  • NAT Gateway を1つ
  • ALB を1つ
  • EC2 を2つ(EBS は計3つ)


これらのリソースですが、Skill の設定後、Skill の利用検証のために新規作成したものとなります。
そのため AWS アカウント内での残存期間が短く、つまり新規リソースであるため、これから使用されるリソース群と AI に判定され、全て削除外と評価されるかもしれませんが、どのように評価されるか、Skill を動かしてみます。

Gemini CLI に入力するプロンプトは以下です。

不要リソース調査をしてください。対象リージョンは東京です。

Gemini CLI を立ち上げ、プロンプトを実行します。
(先ほど作成した Skill はグローバルに使用できる形としているので、Skill 作成時とは異なるディレクトリで Gemini CLI の立ち上げをしています)
設定した Skill の使用を選定してくれています。

スクリプトを実行し、東京リージョン(ap-northeast-1)の不要リソースが調査されます。

調査結果としては、EC2インスタンス、EBSボリューム、Elastic IP の使用状況をスクリプトの実行結果ベースで見たものとなりました。

✦ I will run the unused resource detection script for the Tokyo region (ap-northeast-1).
〜〜省略〜〜
✦ 東京リージョン (ap-northeast-1) での不要リソース調査が完了しました。

  調査結果:

   * EC2 インスタンス: 停止中のインスタンスや、過去7日間でCPU使用率が極端に低い (1%未満) インスタンスは見つかりませんでした。
   * EBS ボリューム: インスタンスにアタッチされていない (未使用的) ボリュームは見つかりませんでした。
   * Elastic IPs: 関連付けされていない (未使用の) Elastic IP は見つかりませんでした。

  現時点では、これらのカテゴリにおいて削除推奨となるリソースは検出されませんでした。他に調査したいサービスやリージョンはありますか?

ALB、NAT Gateway に関する言及がないので、以下のプロンプトを追加で実行します。

ALBとNAT Gatewayも調査してください

実行したところ、Skill のスクリプトに ALB と NAT Gateway のロジックがないため、スクリプトへのロジック追加の編集が始まりました。

✦ I will update find_unused_resources.py to include checks for unused Application Load Balancers (ALBs) and NAT
  Gateways, utilizing CloudWatch metrics to identify inactivity over the past 7 days. I will also fix the
  deprecated datetime usage.

スクリプトの編集後、再度スクリプトが実行され、調査結果が出力されました。

ALB と NAT Gateway の調査結果が追加されています。

✦ ALBとNAT Gatewayの調査を追加して再実行しました。

  追加調査結果:

   * ALB: om-prd-skill-alb という名前のALBが、過去7日間でリクエスト数0のため、未使用の可能性があります。
   * NAT Gateway: 過去7日間のトラフィックが0のNAT Gatewayは見つかりませんでした。

  前回の調査結果 (再掲):
   * EC2: 未使用リソースなし
   * EBS: 未使用リソースなし
   * EIP: 未使用リソースなし

  ALB om-prd-skill-alb について、削除しても問題ないか確認することをお勧めします。

Skill の実行結果としては、こちらのブログの時と同様、ALB の削除を提案するものとなりました。

ALB と NAT Gateway のロジックを追加したスクリプトの内容は以下となります。
ALB については実トラフィック有無ベースの未使用判定(過去7日間の RequestCount 合計が 0)、NAT Gateway については通信量ゼロ判定(過去7日間の In + Out の合計が 0 bytes)の処理が追加されました。


find_unused_resources.py

#!/usr/bin/env python3
import boto3
import argparse
import sys
from datetime import datetime, timedelta, timezone

def get_boto3_client(service, region):
    return boto3.client(service, region_name=region)

def get_metric_sum(cw_client, namespace, metric_name, dimensions, start_time, end_time):
    try:
        metrics = cw_client.get_metric_statistics(
            Namespace=namespace,
            MetricName=metric_name,
            Dimensions=dimensions,
            StartTime=start_time,
            EndTime=end_time,
            Period=86400 * 7, # 7 days as one period to get total sum
            Statistics=['Sum']
        )
        if metrics['Datapoints']:
            return metrics['Datapoints'][0]['Sum']
        return 0.0
    except Exception as e:
        print(f"  Warning: Could not get metrics for {metric_name}: {e}")
        return None

def check_ec2_instances(region):
    print(f"--- Checking EC2 Instances in {region} ---")
    ec2 = get_boto3_client('ec2', region)
    cw = get_boto3_client('cloudwatch', region)

    try:
        response = ec2.describe_instances(Filters=[{'Name': 'instance-state-name', 'Values': ['running', 'stopped']}])
        instances = []
        for r in response['Reservations']:
            instances.extend(r['Instances'])

        unused_instances = []

        for i in instances:
            instance_id = i['InstanceId']
            state = i['State']['Name']
            name = next((t['Value'] for t in i.get('Tags', []) if t['Key'] == 'Name'), instance_id)

            if state == 'stopped':
                unused_instances.append(f"[STOPPED] {name} ({instance_id}) is stopped.")
            elif state == 'running':
                # Check CPU utilization for the last 7 days
                end_time = datetime.now(timezone.utc)
                start_time = end_time - timedelta(days=7)

                try:
                    metrics = cw.get_metric_statistics(
                        Namespace='AWS/EC2',
                        MetricName='CPUUtilization',
                        Dimensions=[{'Name': 'InstanceId', 'Value': instance_id}],
                        StartTime=start_time,
                        EndTime=end_time,
                        Period=86400, # 1 day
                        Statistics=['Average']
                    )

                    if metrics['Datapoints']:
                        avg_cpu = sum([d['Average'] for d in metrics['Datapoints']]) / len(metrics['Datapoints'])
                        if avg_cpu < 1.0:
                             unused_instances.append(f"[LOW CPU] {name} ({instance_id}) has < 1% avg CPU over 7 days ({avg_cpu:.2f}%).")
                    else:
                         # No data often means it hasn't been running long or monitoring is off
                         pass 
                except Exception as e:
                    print(f"  Warning: Could not get metrics for {instance_id}: {e}")

        if unused_instances:
            for item in unused_instances:
                print(item)
        else:
            print("No clearly unused EC2 instances found.")

    except Exception as e:
        print(f"Error checking EC2 instances: {e}")

def check_ebs_volumes(region):
    print(f"\n--- Checking EBS Volumes in {region} ---")
    ec2 = get_boto3_client('ec2', region)

    try:
        response = ec2.describe_volumes(Filters=[{'Name': 'status', 'Values': ['available']}])
        volumes = response['Volumes']

        if volumes:
            for v in volumes:
                vol_id = v['VolumeId']
                size = v['Size']
                # CreateTime is already timezone-aware in boto3
                created = v['CreateTime'].strftime('%Y-%m-%d')
                print(f"[UNATTACHED] {vol_id} ({size} GiB) created on {created} is available.")
        else:
            print("No unattached EBS volumes found.")

    except Exception as e:
        print(f"Error checking EBS volumes: {e}")

def check_eips(region):
    print(f"\n--- Checking Elastic IPs in {region} ---")
    ec2 = get_boto3_client('ec2', region)

    try:
        response = ec2.describe_addresses()
        eips = response['Addresses']

        found = False
        for eip in eips:
            if 'AssociationId' not in eip:
                print(f"[UNASSOCIATED] {eip['PublicIp']} is not associated with any resource.")
                found = True

        if not found:
            print("No unassociated Elastic IPs found.")

    except Exception as e:
        print(f"Error checking Elastic IPs: {e}")

def check_albs(region):
    print(f"\n--- Checking ALBs in {region} ---")
    elbv2 = get_boto3_client('elbv2', region)
    cw = get_boto3_client('cloudwatch', region)

    try:
        response = elbv2.describe_load_balancers()
        albs = [lb for lb in response['LoadBalancers'] if lb['Type'] == 'application']

        unused_albs = []
        end_time = datetime.now(timezone.utc)
        start_time = end_time - timedelta(days=7)

        for alb in albs:
            arn = alb['LoadBalancerArn']
            name = alb['LoadBalancerName']
            # Metric dimensions for ALB require the full LoadBalancer suffix (e.g., app/my-load-balancer/50dc6c495c0c9188)
            # The ARN format is arn:aws:elasticloadbalancing:region:account-id:loadbalancer/app/load-balancer-name/load-balancer-id
            lb_dimension_value = "/".join(arn.split("/")[-3:])

            req_count = get_metric_sum(cw, 'AWS/ApplicationELB', 'RequestCount', [{'Name': 'LoadBalancer', 'Value': lb_dimension_value}], start_time, end_time)

            if req_count is not None and req_count == 0:
                unused_albs.append(f"[NO TRAFFIC] ALB {name} has 0 requests over the last 7 days.")

        if unused_albs:
            for item in unused_albs:
                print(item)
        else:
            print("No unused ALBs found (based on 0 requests in 7 days).")

    except Exception as e:
        print(f"Error checking ALBs: {e}")

def check_nat_gateways(region):
    print(f"\n--- Checking NAT Gateways in {region} ---")
    ec2 = get_boto3_client('ec2', region)
    cw = get_boto3_client('cloudwatch', region)

    try:
        response = ec2.describe_nat_gateways(Filters=[{'Name': 'state', 'Values': ['available']}])
        nat_gateways = response['NatGateways']

        unused_nats = []
        end_time = datetime.now(timezone.utc)
        start_time = end_time - timedelta(days=7)

        for nat in nat_gateways:
            nat_id = nat['NatGatewayId']
            # Name tag
            name = next((t['Value'] for t in nat.get('Tags', []) if t['Key'] == 'Name'), nat_id)

            # Check traffic metrics
            bytes_in = get_metric_sum(cw, 'AWS/NATGateway', 'BytesInFromSource', [{'Name': 'NatGatewayId', 'Value': nat_id}], start_time, end_time)
            bytes_out = get_metric_sum(cw, 'AWS/NATGateway', 'BytesOutToDestination', [{'Name': 'NatGatewayId', 'Value': nat_id}], start_time, end_time)

            total_bytes = (bytes_in or 0) + (bytes_out or 0)

            if total_bytes == 0:
                unused_nats.append(f"[NO TRAFFIC] NAT Gateway {name} ({nat_id}) has 0 bytes processed over the last 7 days.")

        if unused_nats:
            for item in unused_nats:
                print(item)
        else:
            print("No unused NAT Gateways found (based on 0 bytes in 7 days).")

    except Exception as e:
        print(f"Error checking NAT Gateways: {e}")

def main():
    parser = argparse.ArgumentParser(description="Find unused AWS resources.")
    parser.add_argument("--region", type=str, required=True, help="AWS Region to check")
    args = parser.parse_args()

    print(f"Scanning for unused resources in region: {args.region}\n")

    check_ec2_instances(args.region)
    check_ebs_volumes(args.region)
    check_eips(args.region)
    check_albs(args.region)
    check_nat_gateways(args.region)

    print("\nScan complete.")

if __name__ == "__main__":

aws-unused-resource-searcher Skill の実行はこれで以上です。

4.おわりに

本ブログでは Gemini CLI の組み込み skill-creator を使っての Skill 作成と実行結果を紹介しました。
最初のプロンプト実行だけでそれなりの Skill が生成され、さらに boto3 が使える環境であることを検出した上で Python スクリプトの生成が行われたのは予想外でした。

実行結果はこちらのブログと同じ(ALB の削除提案)であったことから、今回の題材(AWS アカウント内のリソース使用実態有無調査)では Anthropic が公開している skill-creator と Gemini CLI の組み込み skill-creator とで得られるアウトプットの品質は変わらないことが確認できました。
Gemini CLI の skill-creator のリポジトリを見たところ、本ブログ執筆時点では SKILL.md の内容が Anthropic が公開している skill-creator とほぼ同一でしたので、その点を踏まえても今回の結果は妥当かと思います)

日常業務に追われ、Skill を作成したくても後回しにしてしまうことがあるかと思いますが、skill-creator を活用すれば、Skill 作成の手間が削減できます。
興味が湧いた方は、ぜひ試してみてください。