Claude Codeのaws-amplifyプラグインでAmplify Gen 2を段階的に作る
aws-amplifyプラグインのamplify-workflowが、バックエンド・sandbox・フロント接続・本番の順に進める流れと、認証・データ・ストレージの落とし穴を示します。
aws-amplifyプラグインは、AWS Amplify Gen 2のバックエンドを、Claude Codeに段階を踏ませて作らせるための部品です。中心にあるのはamplify-workflowというskillで、認証・データ・ストレージ・関数をamplify/ディレクトリのTypeScriptとして書かせ、sandboxで動かしてから本番へ進めます。
この記事では、プラグインの導入から、一言の依頼がどの順に展開されるか、認証・データ・ストレージの各段階で知っておくと手戻りが減る点までを扱います。
amplify-workflowは何を順番に進めるのか
Amplify Gen 2をTypeScriptのコードファーストで開発し、AWS公式のAgent SOP(標準作業手順)に沿って進めるのがこのプラグインの流れです。段階は4つあります。
amplify-workflowの4段階
- 1
Backend
auth・data・storage・functionsのAmplify Gen 2リソースを作ります。
- 2
Sandbox
テスト用のsandboxにデプロイします。
- 3
Frontend & Test
フロントエンドをバックエンドにつなぎ、ローカルで確かめます。
- 4
Production
本番へデプロイします。
依頼内容に当てはまる段階だけが走ります。「認証を足して」と頼めば、本番デプロイまでは走りません。
起動の合図になる言い回しも決まっています。リポジトリの表には、amplify-workflowの発動語として「build Amplify app」「create Amplify project」「add auth to Amplify」「deploy Amplify」「full-stack Amplify」が並びます。skill本体の説明文は、これに加えてamplify/ディレクトリがあるプロジェクトや、@aws-amplifyパッケージを読み込むコード、defineBackend・defineAuth・defineData・defineStorage・npx ampxといった語も起動の条件にしています。日本語で頼む場合も、コード側にこれらの語があれば拾われる設計です。
対象外もあります。Amplify Gen1(amplify CLI v6)、Amplifyを使わないSAMやCDKだけの構成、AI Kitを介さないBedrock直接利用は範囲外です。サーバーレス単体の構成は兄弟プラグインの領分で、aws-serverlessプラグインの記事にまとめています。
導入手順と前提条件
導入はマーケットプレイスの追加とプラグインの有効化の2コマンドです。
/plugin marketplace add awslabs/agent-plugins
/plugin install aws-amplify@agent-plugins-for-aws@の後ろはマーケットプレイス名で、リポジトリ側の案内ではagent-plugins-for-awsです。経路の違いはclaude plugin installの導入経路の記事、マーケットプレイスの仕組みはプラグインとマーケットプレイスの解説を見てください。
動かす前に満たす条件は3つです。
- Node.jsが
^18.19.0 || ^20.6.0 || >=22で、npmが使える - AWS認証情報が設定済みで、
aws sts get-caller-identityが成功する - sandboxを使うなら、
npx ampx --versionがバージョンを返す
プラグインに同梱されるMCPサーバーはaws-mcp1つで、uvx経由でmcp-proxy-for-awsを起動し、AWSのドキュメントと手順の取得に使います。ただしAmplify Gen 2の主作業はコードを書いてnpx ampxを叩くことなので、AWS MCPのツールは必須ではありません。MCPが使えない環境では、Web検索かaws CLIで代替します。
マーケットプレイスの掲載ページは、このプラグインを「認証・データモデル・ストレージ・GraphQL API・Lambda関数のガイド付きワークフロー」と紹介しています。
一言の依頼がどう展開されるか
READMEの例文は「Build me a task management app with Amplify」のような一言です。ここでの要点は、skillが聞き返す項目を決めていることです。
| 状況 | skillの既定 |
|---|---|
| Webでフレームワーク未指定 | skillの既定React(Vite)を選び、理由を説明する |
| モバイル | skillの既定既定なし。Flutter・Swift・Android・React Nativeのどれかを必ず聞く |
| Webかモバイルか不明 | skillの既定進める前に必ず聞く |
| 認証方式 | skillの既定既定なし。メール・ソーシャル・SAML・パスワードレスなどを必ず聞く |
| パッケージマネージャー | skillの既定npm |
| Next.js | skillの既定App Router |
認証方式を勝手に決めない点は、運用上大きな意味があります。セキュリティに直結する選択を、Claudeの推測に任せない作りだからです。
最初の依頼は、たとえば次のように書けます。
Amplify Gen 2でタスク管理アプリを作って。
WebはReact、ログインはメールアドレスとパスワード。
まずバックエンドとsandboxまで。「まずsandboxまで」と範囲を切っておくと、本番デプロイ側の手順に入る前に止められます。
バックエンドの足場づくり
プロジェクトの作り方には厳しい規則があります。プロジェクトは公式のスターターテンプレートから始めます。手書きで構造を組むと、Amplify Hostingのデプロイ検出が壊れる可能性があるためです。React(Vite)ならaws-samples/amplify-vite-react-templateをcloneする流れです。
既存のWebプロジェクトに足す場合は、次のコマンドを使います。
npm create amplify@latest -y-yを付けないと対話が始まるので、必ず付けます。これでamplify/ディレクトリとバックエンド依存が入ります。スターターを使った後にこのコマンドを忘れるとamplify/が無いままになり、足場づくりで最も多い失敗になります。
もう一つの順序の罠が、sandboxの先行実行です。フロントエンドはamplify_outputs.jsonを読み込みますが、このファイルはgitignore対象で、sandboxかCI/CDのビルドが生成します。npm run devを先に叩くとコンパイルできません。
npx ampx sandbox --once
npm run dev--onceを付けないと、sandboxはファイル監視を始めて終了しません。エージェントやCIの環境で固まる原因になるため、非対話環境では--onceが必須です。初めてのアカウント・リージョンではCDKのブートストラップが要り、案内に従うか、もう一度npx ampx sandbox --onceを実行します。
認証・データ・ストレージを足すときの要点
各機能には専用の参照ファイルがあり、skillは該当ファイルを読んでから書く手順です。生成物の形をつかむために、リソースファイルの骨格を見ておきます。以下は参照ファイルのサンプルに沿った例で、Claudeの実出力ではありません。
認証(defineAuth)
// amplify/auth/resource.ts
import { defineAuth } from '@aws-amplify/backend';
export const auth = defineAuth({
loginWith: { email: true },
});作ったリソースはamplify/backend.tsのdefineBackend({ auth })に登録しないと反映されません。参照ファイルが挙げる落とし穴を3つ拾います。
- Cognitoのトリガー関数は、
defineFunctionで定義するだけでなくdefineAuthのtriggersにも登録しないと、デプロイされても発火しません - ソーシャルログインのクライアントシークレットは、文字列で直書きせず
secret()を使います - MFAでSMSを有効にするなら、ユーザープールに電話番号属性が要ります
もう一点は、ゲストアクセスです。参照ファイルによれば、Amplify Gen 2ではゲスト(未認証)アクセスが既定で有効で、Cognito IDプールがallowUnauthenticatedIdentities: trueで作られます。無効にしたい場合はbackend.tsでCDKの上書きを書きます。この既定値はプラグインを使う前から存在する仕様ですが、Claudeに任せるときは確認を忘れやすい項目です。
データ(defineData)
// amplify/data/resource.ts
const schema = a.schema({
Todo: a.model({
content: a.string().required(),
done: a.boolean().default(false),
}).authorization(allow => [allow.owner()]),
});
export type Schema = ClientSchema<typeof schema>;
export const data = defineData({
schema,
authorizationModes: { defaultAuthorizationMode: 'userPool' },
});skillの既定では、認証がまだ無い段階のデータ認可はallow.publicApiKey()で、認証を足したらallow.owner()とdefaultAuthorizationMode: 'userPool'へ切り替えます。defaultAuthorizationModeは、モデルの認可ルールのどれかと対応していなければなりません。userPoolはowner()・authenticated()・group()、apiKeyはpublicApiKey()、iamはguest()に対応します。
つまずきやすい点も具体的です。
Schema型のexportを忘れると、フロントのgenerateClient<Schema>()が型情報を失います- 外部キーを
a.string()で書くと、リレーションが黙ってnullを返します。a.id()を使います a.enum()には.default()が効かず、デプロイ時にエラーも出ずに無視されますpublicApiKey()を使いながら既定をuserPoolにしてapiKeyAuthorizationModeを足さないと、APIキーのリクエストが拒否されます
ストレージ(defineStorage)
アクセス規則はパスごとに書きます。
// amplify/storage/resource.ts
export const storage = defineStorage({
name: 'myFiles',
access: (allow) => ({
'private/{entity_id}/*': [
allow.entity('identity').to(['read', 'write', 'delete']),
],
}),
});ここで間違えやすいのが括弧です。ストレージの規則ではallow.guestとallow.authenticatedは括弧なしのプロパティで、データの認可規則ではallow.guest()のようにメソッドとして呼びます。混ぜるとTypeScriptエラーになります。
パスの書き方にも規則があります。末尾は/*で、先頭に/を付けません。private/*のように{entity_id}を落とすと、認証済みの全ユーザーが他人のprivateファイルに触れてしまいます。.to()を省いた規則は、権限が何も付かないまま黙って無視されます。
関数とフロントエンドをつなぐ
Backend段階の関数(functions)と、Frontend & Test段階の接続にも、それぞれ定型と落とし穴があります。
関数(defineFunction)
Lambda関数はamplify/functions/<名前>/resource.tsで定義し、handler.tsに処理を書きます。
// amplify/functions/my-func/resource.ts
import { defineFunction } from '@aws-amplify/backend';
export const myFunc = defineFunction({
name: 'my-func',
entry: './handler.ts',
timeoutSeconds: 30, // 既定は3、上限は900
runtime: 22, // 数値で書く
});認証と同じく、amplify/backend.tsのdefineBackend({ auth, myFunc })に渡さないとデプロイされません。つまずきやすい点は次のとおりです。
runtimeは整数で書きます。"nodejs22.x"のような文字列はビルドエラーになります- 関数には、他のリソースへのアクセス権が最初から付いていません。データやストレージを触らせるなら、
backend.tsで権限を付与します - APIキーなどは
environmentに文字列で書かず、secret()を使います。sandboxで登録したシークレットは、Amplify Hostingの本番環境では使えません - 独自のREST APIでは、REST(v1)は
APIGatewayProxyHandler、HTTP API(v2)はAPIGatewayProxyHandlerV2と、ハンドラーの型が分かれます。混ぜると応答が壊れます
AppSyncに乗せる独自ロジックなら、a.query()やa.mutation()に.handler()で関数をつなぐ方法が、型が付く分だけ第一候補です。API Gatewayが要るのは、REST形式のURLやWebhookが必要なときです。
フロントエンドの接続
フロントは、生成されたamplify_outputs.jsonを読み込んでAmplify.configure()を呼びます。React(Vite)ならsrc/main.tsxです。
import { Amplify } from 'aws-amplify';
import outputs from '../amplify_outputs.json';
Amplify.configure(outputs);Next.js(App Router)ではapp/layout.tsxに置き、Amplify.configure(outputs, { ssr: true })とssrを付けます。このssrはNext.jsだけの指定で、ほかのフレームワークでは付けません。
置き場所を間違えたり、このimportを忘れたりすると、アプリは起動するのにAmplifyのAPI呼び出しがエラーなしで空の結果を返します。データの呼び出しはgenerateClient<Schema>()で型を付けますが、Next.jsのサーバーコンポーネントではブラウザのセッションが無くgenerateClientが黙って失敗するため、@aws-amplify/adapter-nextjs/dataのgenerateServerClientUsingCookiesを使います。
本番デプロイと権限の歯止め
本番は、AmplifyアプリをAWS CLIで作り、IAMサービスロールを付け、ブランチをつないでamplify.ymlでビルドする流れです。リポジトリはgithub.com/user/repoの形式で渡し、https://を付けるとcreate-appが黙って失敗します。IAMサービスロールを飛ばすと、バックエンドのデプロイが毎回AccessDeniedExceptionになります。Viteの出力先はdistなので、baseDirectoryにbuildを書くと本番が空白ページになる、という警告もあります。
このスキルはaws amplify create-appやnpx ampx sandboxといった、AWSアカウントへ実際に変更を加えるコマンドを走らせます。Claude Code側で、確認を挟む設定を入れておくと安心です。権限ルールはdeny、ask、allowの順に評価され、最初に一致したものが結果を決めます。
{
"permissions": {
"ask": [
"Bash(npx ampx *)",
"Bash(aws amplify *)"
]
}
}この例では、sandboxの作成と本番の操作が、毎回承認の対象になります。ルールの書き方は/permissionsコマンドの記事で扱っています。
skillの安全面の方針は3点です。認証情報はsecret()で扱い、resources: ['*']のようなIAMの広い指定を本番で避け、CI/CDでは長期アクセスキーでなく一時的な認証情報を使います。
後継のAgent Toolkit for AWSとの関係
リポジトリのREADMEの告知では、Agent Toolkit for AWSが公開済みで、AWS Labsにあったプラグインやskillの後継です。本番ソフトウェアを作る場合はそちらが勧められています。このリポジトリも引き続き動作し、貢献も受け付けます。aws-amplifyプラグインの移行先は、告知に記載がありません。
まとめ
amplify-workflowの価値は、Amplify Gen 2で順序を間違えると黙って壊れる箇所を、先回りして守らせる点にあります。スターターテンプレート、-y、sandboxの--once、Schemaのexportなど、どれも一つ外すと原因が見えにくい種類です。
一方で、認証方式を聞かれたときの答え、ゲストアクセスを残すかどうか、本番のIAMの範囲は人が決める部分です。最初の依頼でsandboxまでに範囲を切り、AWSを変更するコマンドをaskに置いて、判断と承認を手元に残せます。