Claude CodeでQuarkusアプリを開発する — devモードとテストの使い分け
Claude CodeでQuarkusアプリを開発するときの、quarkus devのライブリロードと継続テスト、一発実行のテストの役割分担を整理し、CLAUDE.mdのビルドコマンドと許可ルールの例を示します。
Quarkusは、Javaアプリを開発中の自動リロード込みで動かせるフレームワークです。Claude CodeでQuarkusを扱うときの要点は、quarkus devを動かし続ける役と、テストを一発で走らせて結果を読む役を分けることにあります。この記事では、その分担と、CLAUDE.mdに書くビルドコマンド、承認プロンプトを減らす許可ルールを、Maven版とGradle版の両方で示します。
Quarkusの開発ループとClaude Codeの相性
Quarkusには開発モード(dev mode)があります。起動したまま、Javaソースやリソース、設定ファイルを書き換えると、変更がバックグラウンドコンパイルで取り込まれます。ブラウザを更新したりリクエストを送ったりした時点でワークスペースの変更が検出され、コンパイルと再デプロイを経てリクエストが処理されます。コンパイルやデプロイに失敗したときは、エラーページで知らせる仕組みです。
この性質は、コードを書いては動かして確かめるClaude Codeの反復と噛み合います。Claudeがファイルを編集し、アプリを再起動せずにHTTPリクエストで挙動を見る。この往復が、ビルド一式の再実行なしで回ります。
一方で、dev modeは「常駐するプロセス」です。Claude Codeが前面で実行すると、そのコマンドが終わるまで次の作業に進めません。常駐プロセスはバックグラウンド起動に回し、検証用のテストは終了するコマンドで走らせる。この切り分けが本記事の主題です。
SpringのREST API開発との違いを先に知りたいときは、Claude CodeでSpring Bootアプリを作るも参照してください。Quarkusは再読み込みとテストの実行を開発モードの中に持つので、その常駐プロセスをどう扱うかが運用の分かれ目になります。
雛形とコマンドの対応表
プロジェクトの雛形は、Claudeに手書きさせず、Quarkus CLIまたはMavenプラグインで作るのが安全です。ビルド構成の「型」を最初から外さずに済みます。
quarkus create app my-groupId:my-artifactIdCLIを入れていない環境では、Mavenプラグインのcreateゴールが使えます。-DprojectGroupIdと-DprojectArtifactIdを渡します(artifactIdは必須で、渡さなければ対話モードになります)。ガイドのコマンド例ではプラグインのバージョンが3.40.1になっています。実際に使うときは、使う版に合わせて書き換えてください。
作ったあとの日常コマンドは、次の表のとおりです。Claudeに覚えさせる対象はここです。
| 目的 | Quarkus CLI | Maven | Gradle |
|---|---|---|---|
| 開発モード起動 | Quarkus CLIquarkus dev | Maven./mvnw quarkus:dev | Gradle./gradlew --console=plain quarkusDev |
| 継続テストのみ | Quarkus CLIquarkus test | Maven./mvnw quarkus:test | Gradle./gradlew quarkusTest |
| ビルド | Quarkus CLIquarkus build | Maven./mvnw install | Gradle./gradlew build |
| 拡張の追加 | Quarkus CLIquarkus ext add | Maven./mvnw quarkus:add-extension -Dextensions='…' | Gradle./gradlew addExtension --extensions='…' |
Quarkusの雛形は、Gradleラッパー(./gradlew)を自動で入れます。Mavenのガイドも、コマンド例を./mvnwで書いています。CLAUDE.mdにもmvnではなく./mvnwと書いておくと、Claudeが使うコマンドの揺れを抑えられます。
devモードをバックグラウンドで動かしてClaudeに触らせる
Claude Codeには、devサーバーのような長時間プロセス向けに、Bashコマンドをバックグラウンドタスクとして起動する機能があります。起動したタスクは/tasksで一覧でき、停止もできます。quarkus devはまさにこの用途です。
quarkus dev をバックグラウンドで起動して、起動ログに
"Listening on" が出たらcurlで /hello を叩いて確認してこう頼むと、起動待ちとHTTP確認の流れをClaude側で組めます。ログの特定の行に反応させたいときは、出力を1行ずつClaudeに返すMonitorツールも使えます。たとえば例外のスタックトレースが出た瞬間にClaudeが気づく、という使い方です。
変更がどこまで自動で反映されるか
ライブリロードの対象は、Javaソース、リソース、application.propertiesです。反映のきっかけは、ブラウザやクライアントからのリクエストです。ファイルを保存しただけでは次のリクエストまで再コンパイルされない点は、確認ループを書くときに押さえておきます。
pom.xmlは別扱いです。Quarkusはpom.xmlの変更を検出すると、必要に応じてMavenプロセスごと再起動します。拡張を足した直後は、この再起動を経るため反映に時間がかかります。Claudeに依存を追加させたあとは、少し待ってから動作確認させる手順が無難です。
デバッグポートと注意点
dev modeは既定でデバッグモードで起動し、ポート5005で待ち受けます。JVMは停止しません。-Ddebug=falseを渡すとデバッグを無効にでき、-Dsuspend -DdebugではJVMを一時停止した状態で起動します。
既定のデバッグホストは、安全のためlocalhostです。コンテナ内でdev modeを動かすなど、他のホストからアタッチしたいときだけ-DdebugHost=0.0.0.0を指定します。Claudeに「デバッグ用に開けて」と任せるより、必要な場面を人が決めたほうが安全です。
リモート開発モード(quarkus.package.jar.type=mutable-jarとライブリロード用のパスワードを設定する方式)も用意されています。ただし本番アプリをdev modeで動かしてはいけない、とガイドが明記しています。Claudeに設定を書かせる際は、この用途がローカルや開発環境に限られることをCLAUDE.mdに添えておくと、誤用を防げます。
テストの実行方法は役割で分ける
Quarkusでテストを動かす方法は複数あり、役割がはっきり違います。Claudeに任せるときも、混ぜないほうが結果を読みやすくなります。
| 層 | コマンド | 向く場面 | 注意 |
|---|---|---|---|
| 継続テスト(dev mode内) | コマンドquarkus devの画面でrキー | 向く場面人がログを見ながら編集とテストを往復する | 注意既定は一時停止状態 |
| 継続テストのみ | コマンド./mvnw quarkus:test / ./gradlew quarkusTest | 向く場面devモードと同じポートを使うモックと衝突するとき | 注意Dev UIは使えない |
| 一発実行 | コマンド./mvnw test / ./gradlew test | 向く場面Claudeが結果を読んで判断する検証 | 注意終了コードで成否が出る |
| ビルド成果物のテスト | コマンド@QuarkusIntegrationTest | 向く場面jarやネイティブ実行ファイルを検証する | 注意統合テスト用の実行手順が別 |
継続テストは「rキーで再開」が前提
Quarkusの継続テスト(continuous testing)は、コードの変更を保存した直後にテストを再実行します。どのテストがどのコードをカバーするかを検出し、関係するテストだけを走らせます。
dev modeを起動すると、画面下部にTests paused, press [r] to resume, [h] for more options>と表示されます。rキーでテストが始まり、結果行には[r]再実行、[v]全結果の表示、[p]一時停止などの操作が出ます。
自動で始めたいときは、application.propertiesにquarkus.test.continuous-testing=enabledを書きます。取りうる値はpaused、enabled、disabledで、既定はpausedです。disabledにすると、アプリを再起動しない限り有効化できません。環境変数ならQUARKUS_TEST_CONTINUOUS_TESTINGです。
キー入力が前提の画面は、バックグラウンドタスクのClaudeには扱いにくい部分があります。そこで、人が使うターミナルのdev modeでは継続テストを活かし、Claudeには一発実行のテストを頼む、という分担を提案します。もしClaudeに継続テストの結果を拾わせたいなら、enabledに設定したうえでログを監視させる方法があります。
継続テストだけを動かす
devモードがテストの邪魔になるケースがあります。ガイドの例は、同じポートでWireMockを動かす場合です。そのときは、Mavenなら./mvnw quarkus:test、Gradleなら./gradlew quarkusTestで、dev modeなしに継続テストだけを走らせられます。Dev UIはdev modeが提供するため、このモードでは使えません。
対象のテストを絞るには、Mavenで-Dtest=…、Gradleで--tests …が使えます。どちらもmvn testやgradle testと同じ書式で、指定するとquarkus.test.include-patternなどの設定は無視されます。大きなプロジェクトで「今触っているテストだけ」を回させるときに便利です。
一発実行はClaudeに任せる
ここが検証の中心です。./mvnw testや./gradlew testは、終了したときの出力と終了コードで成否が決まります。Claudeはその結果を読んで、修正と再実行を繰り返せます。
@QuarkusTestを付けたテストは、アプリを実際に起動したうえでテストを実行します。HTTPの確認にはREST Assuredが相性良く、Quarkusのテスト統合がデフォルトのポートを自動設定します。最小のテストは次の形です。
@QuarkusTest
public class GreetingResourceTest {
@Test
public void testHelloEndpoint() {
given()
.when().get("/hello")
.then()
.statusCode(200)
.body(is("hello"));
}
}依存は、Mavenでquarkus-junitとrest-assured(testスコープ)です。GradleではtestImplementationに同じ2つを書きます。JUnitを使うため、Surefireプラグインのバージョン指定と、java.util.logging.managerのシステムプロパティ設定が必要です。雛形はこれらを備えているので、Claudeにpom.xmlを書き換えさせるときは、この部分を消さないよう指示します。
ビルド成果物は@QuarkusIntegrationTestで検証する
@QuarkusIntegrationTestは、Quarkusビルドが出したjar、ネイティブイメージ、コンテナイメージを起動して検証します。prodプロファイルで動くため、dev用の設定では見えなかった問題を拾えます。
実行手順は通常のテストと別です。Mavenでは-DskipITs=false、GradleではquarkusIntTestタスクが必要になります。CLAUDE.mdに書いておかないと、testだけが実行され、成果物の検証が抜け落ちる構成になりえます。
CLAUDE.mdに書くビルドコマンド
CLAUDE.mdは、セッションの開始時に読まれる永続的な指示です。Quarkusプロジェクトでは、次のように書いておきます。Maven版の例です。
## Quarkus 開発ルール
- 開発サーバー: `./mvnw quarkus:dev`(バックグラウンドで起動し、終了させるときは `/tasks` から止める)
- 検証(編集のたびに実行): `./mvnw test`
- 絞り込み: `./mvnw test -Dtest=GreetingResourceTest`
- ビルド成果物の検証: `./mvnw verify -DskipITs=false`(`@QuarkusIntegrationTest` を含む)
- 拡張の追加: `./mvnw quarkus:add-extension -Dextensions='<name>'`(pom.xml の手編集はしない)
- `mvn` ではなく `./mvnw` を使う
- 本番アプリを dev mode で動かさない。mutable-jar は開発環境専用
- Dev Services を使うテストは Docker か Podman が必要。無い環境では実行しないGradle版では、コマンドを次のように読み替えます。
- 開発サーバー: `./gradlew --console=plain quarkusDev`
- 検証: `./gradlew test`
- 絞り込み: `./gradlew test --tests GreetingResourceTest`
- ビルド成果物の検証: `./gradlew quarkusIntTest`コマンドの単位で書く理由は、Claudeが推測しないで済むようにするためです。拡張の追加にadd-extensionを指定しているのは、Quarkusが拡張名の略称を展開するためです。agroalと書けばio.quarkus:quarkus-agroalに解決されるので、座標を調べる手間が省けます。
CLAUDE.mdの書き方の全般はCLAUDE.mdの書き方パターンに整理しています。
許可ルールで承認プロンプトを減らす
検証コマンドのたびに承認を求められると、反復が止まります。プロジェクトの.claude/settings.jsonで、読み取りとテスト系だけを許可し、危険な操作は求める形にします。
{
"permissions": {
"allow": [
"Bash(./mvnw test *)",
"Bash(./mvnw quarkus:dev *)",
"Bash(./mvnw quarkus:info)",
"Bash(./mvnw quarkus:dependency-tree)"
],
"ask": [
"Bash(./mvnw quarkus:add-extension *)",
"Bash(./mvnw install *)"
]
}
}ルールの書き方で押さえたいのは、*をサブコマンドの後ろに置くことです。Bash(./mvnw test *)ならtestで始まるコマンドだけが対象になります。Bash(./mvnw *)のように広げると、installなどの副作用のあるゴールまで通ります。
quarkus:infoやquarkus:updateは、ガイドに「実験的」と明記されたゴールです。quarkus:updateは、更新の候補を報告するだけで適用はしません。依存関係の整合性を確かめる用途で使えますが、出力形式が変わる可能性があるため、結果を機械的に判定する自動化には向きません。
テストの自動実行をhooksで組む方法は、hooksによるテスト自動化を参照してください。Quarkusではdev modeが常駐するため、hooksでテストを走らせる場合は、dev modeと並行して動かしてよいかを先に決めておきます。
つまずきやすい点
Dev Servicesのコンテナが起動しない。Quarkusは、データベースなどの依存サービスをコンテナで自動起動するDev Servicesを持ちます。DockerやPodmanがない環境では、サービスを通常どおり設定する必要があります。すべて止めたいときはquarkus.devservices.enabled=falseです。Claudeが「テストが落ちた」と報告した原因がコンテナの不在だった、というケースがあります。
Gradleで継続テストの表示が崩れる。Gradleはデーモンとして動くため、Quarkusは継続テストの整った画面を描けず、ログ出力にフォールバックします。--console=plainを付けるのはそのためで、Claudeに読ませるログとしても適しています。
依存を足した直後に動作確認が空振りする。 pom.xmlの変更はMavenプロセスの再起動を伴います。追加直後の最初のリクエストは待たされる場合があるため、少し間を置いてから確認させます。
バックグラウンドにdev modeが残る。起動したままのタスクは、/tasksから停止できます。別のdev modeを立ち上げ直す前に、前のものを止めます。
まとめ
Quarkusでは、常駐するdev modeと、結果を返して終わるテストコマンドを分けると、Claude Codeの反復が安定します。dev modeはバックグラウンドで動かして実リクエストを投げ、検証は./mvnw testか./gradlew testで一発実行する。継続テストは人の画面で活かし、成果物の検証は@QuarkusIntegrationTestと専用のコマンドで確認する。この分担と、コマンドのCLAUDE.md記載、test *に幅を絞った許可ルールが、そのまま運用の骨格になります。
同じ「検証コマンドを決めてClaudeに回させる」型は、Goアプリの開発手順にも見られます。言語が変わってもCLAUDE.mdとテスト実行の組み立ては共通で、変わるのはビルドツールの名前だけです。