Claude Media
Claude Codeのaws-amplifyプラグインでAmplify Gen 2を段階的に作る

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. 1

    Backend

    auth・data・storage・functionsのAmplify Gen 2リソースを作ります。

  2. 2

    Sandbox

    テスト用のsandboxにデプロイします。

  3. 3

    Frontend & Test

    フロントエンドをバックエンドにつなぎ、ローカルで確かめます。

  4. 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.jsskillの既定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に置いて、判断と承認を手元に残せます。

この記事を共有:XはてブLinkedIn