
Kiro CLI が Claude Opus 4.8 に対応。Opus モデル別の違いを確認してみた
はじめに
2026年5月29日、Kiro CLI で Anthropic の最新モデル Claude Opus 4.8 が選べるようになりました(Kiro CLI 2.5.0 以上、experimental preview 扱いです)。
Opus 4.8 は 2026年5月28日に Amazon Bedrock および Claude Platform on AWS で提供開始され、翌5月29日に Kiro(IDE / CLI / Web)でも対応が発表されました。
本記事では Kiro CLI 2.5.0 で Opus 4.8 を実際に選択・実行できることを確認し、同一の CloudFormation テンプレート解析タスクでモデル世代(4.8 / 4.7 / 4.6)およびエフォート(low〜max)を変えたときの違いを実測しました。
Kiro 上でのモデル一覧とクレジット倍率
/model コマンドで確認できるモデル一覧の抜粋です。Opus 4.x のクレジット倍率はいずれも 2.20x で同一です。
| モデル | クレジット倍率 | 備考 |
|---|---|---|
| claude-opus-4.8 | 2.20x | Experimental preview / 1M コンテキスト |
| claude-opus-4.7 | 2.20x | Experimental preview / 1M コンテキスト |
| claude-opus-4.6 | 2.20x | Claude Opus 4.6 |
| claude-sonnet-4.6 | 1.30x | 最新 Sonnet / 1M コンテキスト |
Kiro 公式ブログによると、対象プランは Kiro Pro / Pro+ / Power で、コンテキストは 1M トークン、最大出力は 128K トークンです。提供リージョンは AWS US-East-1(バージニア北部)と Europe(フランクフルト)でクロスリージョン推論に対応しています。
検証内容
タスクと採点方法
意図的に10個の問題を仕込んだ CloudFormation テンプレート(eval_template.yaml)を Kiro CLI に読み取らせ、アーキテクチャ概要とセキュリティ / ベストプラクティス上の問題点を指摘させました。
eval_template.yaml(仕込み CFn テンプレート)
AWSTemplateFormatVersion: '2010-09-09'
Description: Sample stack for analysis (intentionally contains ~10 planted issues)
Resources:
DataBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: my-app-data-bucket
AccessControl: PublicRead
AppSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: app sg
VpcId: vpc-0abc1234
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
CidrIp: 0.0.0.0/0
AppRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal: { Service: ec2.amazonaws.com }
Action: sts:AssumeRole
Policies:
- PolicyName: full-access
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action: '*'
Resource: '*'
AppInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles: [ !Ref AppRole ]
AppServer:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-0123456789abcdef0
InstanceType: t3.large
IamInstanceProfile: !Ref AppInstanceProfile
SecurityGroupIds: [ !Ref AppSecurityGroup ]
AppDatabase:
Type: AWS::RDS::DBInstance
Properties:
Engine: mysql
DBInstanceClass: db.t3.medium
AllocatedStorage: '20'
MasterUsername: admin
MasterUserPassword: Password123!
PubliclyAccessible: true
StorageEncrypted: false
VPCSecurityGroups: [ !Ref AppSecurityGroup ]
Outputs:
DBEndpoint:
Value: !GetAtt AppDatabase.Endpoint.Address
採点対象の10項目は以下のとおりです。
- S3 公開(PublicRead)
- S3 暗号化なし
- S3 PublicAccessBlock 未設定
- SSH(22番ポート)全開放
- DB ポート(3306)全開放
- IAM 全権限(Action / Resource =
*) - DB パスワード平文ハードコード
- RDS PubliclyAccessible
- RDS ストレージ暗号化なし
- データ保全(削除保護 / 自動バックアップ / スナップショット等)の未設定
採点はキーワード一致をベースにしつつ、表現ゆれによる誤判定は本文を目視確認して補正しました。項目10は削除保護・バックアップ・スナップショット等のいずれかに触れていれば検出とする OR 判定です。
実行方法
ヘッドレスモードで各条件を実行しました。
kiro-cli chat --no-interactive --trust-tools=read --model <model> "<prompt>"
エフォートの切替は以下のように設定しました。
# 明示指定
kiro-cli settings chat.modelDefaults '{"claude-opus-4.8":{"output_config":{"effort":"high"}}}'
# デフォルトに戻す(設定削除)
kiro-cli settings --delete chat.modelDefaults
結果表の時間は Kiro が表示する Time、Credits も Kiro 表示値をそのまま使っています。各条件5回計測し、平均で示しています。
bench.sh(反復計測スクリプト)
#!/usr/bin/env bash
# 同一プロンプトを条件ごとにREPS回くり返し実行し、生出力とインデックスを残す。
# 使い方: ./bench.sh [REPS] [MODE]
# REPS : 各条件のくり返し回数 (default 5)
# MODE : effort | models | both (default effort)
set -uo pipefail
DIR="$(cd "$(dirname "$0")" && pwd)"
REPS="${1:-5}"
MODE="${2:-effort}"
MODEL="claude-opus-4.8"
EFFORTS=(low medium high xhigh max default)
MODELS=(claude-opus-4.8 claude-opus-4.7 claude-opus-4.6)
OUT="$DIR/bench/out"; ERR="$DIR/bench/err"; IDX="$DIR/bench/runs.tsv"
mkdir -p "$OUT" "$ERR"
[ -f "$IDX" ] || printf "cond\trun\twall_sec\toutfile\terrfile\n" > "$IDX"
TPL=$(cat "$DIR/eval_template.yaml")
PROMPT="次のCloudFormationテンプレートを逆解析し、(1)アーキテクチャ概要 と (2)セキュリティ/ベストプラクティス上の問題点 を箇条書きで漏れなく指摘してください。
\`\`\`yaml
$TPL
\`\`\`"
set_effort() {
if [ "$1" = "default" ]; then kiro-cli settings --delete chat.modelDefaults >/dev/null 2>&1
else kiro-cli settings chat.modelDefaults "{\"$MODEL\":{\"output_config\":{\"effort\":\"$1\"}}}" >/dev/null; fi
}
one_run() {
local cond="$1" model="$2" r o e s en wall
for r in $(seq 1 "$REPS"); do
o="$OUT/${cond}_${r}.txt"; e="$ERR/${cond}_${r}.txt"
s=$(date +%s.%N)
timeout 600 kiro-cli chat --no-interactive --trust-tools=read --model "$model" "$PROMPT" > "$o" 2> "$e"
en=$(date +%s.%N); wall=$(echo "$en - $s" | bc)
printf "%s\t%s\t%s\t%s\t%s\n" "$cond" "$r" "$wall" "$o" "$e" >> "$IDX"
echo "[$(date +%T)] $cond run $r/$REPS wall=${wall}s"
done
}
if [ "$MODE" = "effort" ] || [ "$MODE" = "both" ]; then
for ef in "${EFFORTS[@]}"; do set_effort "$ef"; one_run "effort_${ef}" "$MODEL"; done
fi
if [ "$MODE" = "models" ] || [ "$MODE" = "both" ]; then
kiro-cli settings --delete chat.modelDefaults >/dev/null 2>&1
for m in "${MODELS[@]}"; do one_run "model_${m}" "$m"; done
fi
kiro-cli settings --delete chat.modelDefaults >/dev/null 2>&1
echo "[$(date +%T)] DONE. 解析: python3 analyze.py"
analyze.py(統計集計スクリプト)
#!/usr/bin/env python3
"""bench.sh の出力を解析。条件ごとに平均・中央値・外れ値を出力。"""
import re, os, statistics as st
DIR = os.path.dirname(os.path.abspath(__file__))
IDX = os.path.join(DIR, "bench", "runs.tsv")
ANSI = re.compile(r'\x1b\[[0-9;?]*[a-zA-Z]')
CHECKS = {
"S3公開": ["publicread", "パブリック", "公開"],
"S3無暗号": ["bucketencryption", "暗号化されていない", "暗号化されない",
"暗号化未設定", "暗号化が未", "暗号化が無", "暗号化無",
"暗号化なし", "sse-", "暗号化を有効", "保存データが平文"],
"S3ブロック無": ["publicaccessblock", "パブリックアクセスブロック"],
"22全開放": ["22", "ssh"],
"3306全開放": ["3306"],
"IAM全権限": ["action: '*'", "ワイルドカード", "全権限", "'*'", "管理者", "フルアクセス"],
"DBパス平文": ["平文", "ハードコード", "password123", "secrets manager", "直書き"],
"RDS公開": ["publiclyaccessible", "インターネット", "公開され", "パブリックip"],
"RDS無暗号": ["storageencrypted", "保管時", "ストレージ暗号", "保存データが暗号化"],
"削除/バックアップ無": ["deletionpolicy", "削除保護", "スナップショット",
"バックアップ", "multiaz", "multi-az"],
}
def strip(p):
return ANSI.sub("", open(p, encoding="utf-8", errors="replace").read())
def parse_run(outf, errf):
body = strip(outf); lo = body.lower()
detect = sum(any(w in lo for w in ks) for ks in CHECKS.values())
chars = len(re.sub(r"\s", "", body))
err = strip(errf) if os.path.exists(errf) else ""
m = re.search(r'Credits:\s*([\d.]+).*?Time:\s*(\d+)\s*([hms])', err)
credits = float(m.group(1)) if m else None
app_t = None
if m:
v = int(m.group(2))
app_t = v*60 if m.group(3) == "m" else (v*3600 if m.group(3) == "h" else v)
return credits, app_t, detect, chars
def iqr_outliers(vals):
xs = sorted(v for v in vals if v is not None)
if len(xs) < 4:
return set()
q1 = st.quantiles(xs, n=4)[0]; q3 = st.quantiles(xs, n=4)[2]; iqr = q3 - q1
lo, hi = q1 - 1.5*iqr, q3 + 1.5*iqr
return {v for v in xs if v < lo or v > hi}
def stats(vals):
xs = [v for v in vals if v is not None]
if not xs:
return None
return dict(n=len(xs), mean=st.mean(xs), median=st.median(xs),
stdev=(st.pstdev(xs) if len(xs) > 1 else 0.0),
min=min(xs), max=max(xs))
runs = {}
if not os.path.exists(IDX):
raise SystemExit(f"not found: {IDX} (先に ./bench.sh を実行)")
for line in open(IDX):
if line.startswith("cond\t"):
continue
cond, r, wall, outf, errf = line.rstrip("\n").split("\t")
cr, at, det, ch = parse_run(outf, errf)
runs.setdefault(cond, []).append(
dict(run=int(r), wall=float(wall), credits=cr, app_t=at, detect=det, chars=ch))
metrics = [("credits", "cr"), ("app_t", "s"), ("wall", "s"), ("detect", "/10"), ("chars", "")]
for cond in sorted(runs):
rs = runs[cond]; n = len(rs)
print(f"\n===== {cond} (n={n}) =====")
print(f"{'metric':9}{'mean':>9}{'median':>9}{'stdev':>9}{'min':>8}{'max':>8}{' 外れ値(run#)'}")
for key, unit in metrics:
s = stats([x[key] for x in rs])
if not s:
print(f"{key:9}{'n/a':>9}"); continue
outs = iqr_outliers([x[key] for x in rs])
orun = [f"#{x['run']}({x[key]})" for x in rs
if x[key] in outs and x[key] is not None]
print(f"{key:9}{s['mean']:>9.2f}{s['median']:>9.2f}{s['stdev']:>9.2f}"
f"{s['min']:>8.2f}{s['max']:>8.2f} {', '.join(orun) if orun else '-'}")
結果
モデル別比較(エフォート指定なし=各モデルのデフォルト、n=5 平均)
| モデル | 検出(平均) | Credits(平均) | Kiro 表示 Time(平均) | 出力文字数(平均) |
|---|---|---|---|---|
| claude-opus-4.8 | 10/10 | 0.65cr | 36.6s | 約1,940 |
| claude-opus-4.7 | 10/10 | 0.98cr | 50.0s | 約3,000 |
| claude-opus-4.6 | 9.2/10 | 0.32cr | 20.8s | 約1,260 |
差が最も明確だったのはモデル世代でした。4.7 は Credits と時間が最も大きく、回答も長めです。今回の5回平均では 4.8 は 4.7 より Credits と時間が小さく出ました(0.65 vs 0.98cr、36.6 vs 50.0s)。検出は両者とも 10/10 でした。4.6 は最も Credits・時間が小さく(0.32cr / 20.8s)、検出 9.2/10 でした。
4.6 で差が出たのは、主に「S3 PublicAccessBlock 未設定」への言及でした。S3 は PublicAccessBlock を有効にし、公開が必要な場合も CloudFront OAC などを使って直接公開を避ける構成が推奨されるため、今回はベストプラクティス観点として採点対象にしました。4.7 / 4.8 はこの点まで指摘しており、4.6 はこの観点への言及が少なかった、という結果です。
一方で、4.6 も SSH / DB ポートの全開放・IAM 全権限・DB パスワード平文・RDS 公開・RDS 暗号化なしなど、クリティカルなリスクは検出できていました。簡潔さ・速度・Credits を抑えたい用途では十分な選択肢になり得ます。
エフォート別比較(claude-opus-4.8、n=5 平均)
| effort | 検出(平均) | Credits(平均) | Kiro 表示 Time(平均) |
|---|---|---|---|
| low | 10/10 | 0.67cr | 35.4s |
| medium | 10/10 | 0.66cr | 35.6s |
| high | 10/10 | 0.67cr | 34.6s |
| xhigh | 9.6/10 | 0.61cr | 36.6s |
| max | 10/10 | 0.62cr | 33.6s |
| 指定なし(default) | 10/10 | 0.64cr | 34.8s |
low〜max で検出・Credits・時間とも明確な傾向は見られませんでした。少なくとも今回の CloudFormation 解析タスクでは、エフォート変更による最終成果物の差は大きくありませんでした。
まとめ
Kiro CLI 2.5.0 で Claude Opus 4.8 が、プレビュー扱いですが、選択できるようになりました。今回のタスクでは、4.8 は 4.7 と同等の検出力でありながら Credits・時間ともに小さく、デフォルト設定同士の比較では上位互換と思われる結果でした。一方 4.6 は簡潔・高速・低 Credits で、クリティカルなリスクは検出できており、速度や Credits を優先する場面では引き続き有力な選択肢となりそうです。
参考リンク










