こんにちは!皆さん生成 AI を開発で活用していますか?
いま、生成 AI はすでに「特別な技術」ではなくなりつつあります。
かつてはエンジニアや一部の人だけが使っていた ChatGPT のようなツールも、いまでは、テクノロジーに馴染みのなかった人たちも日常的に活用しています。
検索、企画、学習、文章作成…。自分が直接使っていなくても、気づけば使っているサービスの裏側に生成 AI が組み込まれていたり…。
まさに“生活に溶け込むスピード”で広がっていて、その流れの速さには驚かされます。
エンジニアとしてもこの 1 年半ほどで状況は大きく変わりました。
以前は「生成 AI がエンジニアリングを変えるのは、もう少し先かな」と感じていたのですが、いまでは開発現場で生成 AI を使うのが当たり前になりつつあります。
実際、Monstarlab でもプロジェクトごとに手法は異なるものの、ほとんどの現場で何かしらの生成 AI が活用されています。
私自身も、Github Copilot や Cursor を使って、補助的に AI の力を借りながら開発を進めることが増えてきました。
ただ最近、Claude Code を使う機会があり、これまでとはちょっと違った体験をしたことで、「開発における生成 AI との関係性」が大きく変わってきたと感じています。
この記事では、その体験と気づきをまとめてみようと思います。
Co-pilot としての生成 AI 活用
今ではほとんどのエンジニアが利用していると思いますが、いわゆる開発の補助(AI-assisted)としての生成 AI があります。
すでに一般的なものとなっていて、昔はエディタが機械的に限定的なコーディングのアシストをしてくれる程度でしたが、生成 AI との連携により、既存のソースコードや前後の文脈を読み取ってサジェストやコード生成を行ってくれるようになりました。
その結果、ソースコードを書くスピードは大きく向上しました。
私も最近まではこの使い方がメインで、過去には
「コードを書く → 不明点があれば Web で検索やドキュメントを確認 → 試しに書いてみる」というような繰り返しで進めていたのが、エディタ内で完結できる場面が格段に増えました。
とくに GitHub Copilot や Cursor などのツールは、
- よく使う処理の雛形や正規表現をすばやく提案してくれる
- 書き始めの“とっかかり”が早くなる
- 「なんとなくこう書けばよさそう」という思考を具現化してくれる
といった点で、日常の開発効率を確実に上げてくれました。
いまや「ちょっとわからないことがあればとりあえず聞く」「ベースを出してもらってから整える」といったスタイルが当たり前になっていて、生成 AI は“開発のパートナー”として手放せない存在になりつつあります。
ただ、この段階ではあくまで人間が主で、AI はコーディングを助けてくれる“パートナー”にすぎませんでした。
設計も実装方針も人間が考えて、AI はそれを補助する形。
開発の“主導権”はまだこちらにあるという感覚が強かったように思います。
生成 AI が"Pilot"になる感覚
そんな中、Claude Code を使う機会がありました。
これまでのように、AI がちょっとしたコーディングを補助するだけではなく、アプリケーション全体を“構築する側”に回るような体験でした。
具体的には、以下のような進め方を試してみました。
- 全体のアーキテクチャやディレクトリ構成、使用技術の方針を自分で決める
- 作りたいアプリケーションの仕様を、できるだけ詳細にドキュメント化する
- そのドキュメントをもとに、Claude Code や Cursor にタスク単位で指示を出す
- 生成されたコードをレビューしながら、仕様のズレや漏れを軌道修正する
このときの感覚は、まさにClaude Code が"Pilot"で、自分が"Co-pilot"として横に座っているような開発スタイルでした。
特に小さなコンポーネントや補助的なロジックに関しては、明確な設計書がなくてもプロンプトやちょっとした指示だけでテンポよくコードを生成してくれるため、今までの開発と比べて明らかにタスクの消化スピードが早くなったことに驚きました。
さらに、Claude のアップデートが進んでいることもあり、生成されるコードの構造や可読性、初期完成度の高さもどんどん上がっているのを実感できました。
正直に言って、「コードが短時間で大量に生成されて、しかもちゃんと動く」という体験はとても楽しく、 「もしかして、これがこれからの開発のスタンダードになるのでは?」 とすら思いました。
ただし、同時にいくつかの大きな課題も感じました。当たり前のことですが、いくら AI が賢くなってきたとはいえ、雰囲気だけで“よしなに作ってくれる”わけではないのです。
課題も多い ― 設計とレビューの重要性
Claude Code を Pilot のように使う開発体験は、確かに楽しく、スピード感もあって魅力的です。
しかし、実際に進めていく中で、いくつかの重要な課題にも気づかされました。
- 設計が曖昧だと破綻する
まず強く感じたのは、設計がしっかりしていないとすぐに破綻するということです。
Claude Code は柔軟に対応してくれる一方で、こちらが明確な方針を示さないと、その場の情報や雰囲気から「それっぽく」コードを生成します。
ディレクトリ構成、テックスタックの選定、命名規則、責務の分離など、開発の初期段階で設計ルールを明文化しておかないと、ファイル単位では動くけれど、プロジェクト全体としての一貫性がどんどん崩れていきます。
小さなアプリやスクリプトなら問題は少ないかもしれませんが、少しスケールのある開発になると、局所最適の積み重ねが、構造破綻に直結します。
むしろ、AI を活用するからこそ、
最初に設計の“ルール/仕様”を決めておくことの重要性が増していると感じました。
- コードレビュー力が問われる
もう一つの大きな課題は、AI が生成したコードを適切にレビューできるかどうかです。
生成 AI は短時間で大量のコードを生成します。Claude Code の出力は非常に自然で、しかも構造も整っているため、経験が浅いと「これで良さそう」とそのまま通してしまいたくなります。
しかし、実際には以下のようなケースが多々あります:
- ビジネスロジックの解釈がズレている
- 責務が曖昧になっている
- 仕様の意図がうまく反映されていない
- セキュリティ面での配慮が抜けている
「AI が書いたから正しいはず」ではなく、「AI が書いたからこそ疑って見る」 という目線が求められます。
また、AI に生成させる量が多くなればなるほど、レビュー対象のコード量も増え、人間側の負担はむしろ増える可能性もあると感じました。
そのため、レビュー力や設計観点を持っている人ほど、AI を効果的に使えるというのが現時点での実感です。
AI が Pilot になることで開発スピードは確かに上がりましたが、だからこそ、人間が「設計とレビュー」というコアの責務を担う必要性が一層高まっているのだと強く感じています。
とはいえ、生成 AI が生成するコードはとても多く、すべてをレビューすることは現実的ではない場合が多いです。
品質が悪いコード(自分が思っていたものと違う)の大部分は、前段の設計やコンテキストに不足があった場合に生成されていると考えたほうが良く、どうやったら思い通りのものが生成されるのか、足りない情報は何だったのか?を模索することも大切です。
ドキュメントをもとにコードを生成する → うまくいかない部分=曖昧でコンテキストが足りない部分 → ドキュメントに追加する、の繰り返しがとても重要です。
おわりに ― 生成 AI 時代のエンジニアリングとは?
Claude との開発体験を通して、生成 AI はただの便利ツールではなく、
開発の主導権を持つ“パートナー”になりつつあると感じました。
コードの生成スピード、精度、文脈理解力 ──
数年前なら考えられなかったようなクオリティで、「とりあえず任せてみる」ことができるようになってきています。
ただし、それは「何も考えずに任せられる」こととは違います。
むしろ、AI がここまで書けるようになったからこそ、私たち人間側にはより高い視点での判断力と設計力が求められるようになったと感じています。
- この構成で本当にいいのか?
- この責務分離は妥当か?
- ビジネス的な意図とズレていないか?
AI の生成結果に対して、そうした問いを持ち、方向性を調整していくこと、“レビューできる力”が、これまで以上に開発の質を左右するようになっている のだと思います。
生成 AI とともに開発することが当たり前になってきた今、私自身も、 「どう使うか」だけでなく「どう付き合っていくか」 を常に考えるようになりました。
おそらくこれからはツールの名前や精度以上に、 「人と AI の関係性をどうデザインするか」 が問われる時代になるのだと思います。
まだ正解はないかもしれませんが、今回のような体験を通じて、自分なりのスタンスを少しずつ築いていけたらと思っています。
補足/Claude Code での開発 TIPS
いくつかこれは単純に便利!ちょっと困った!ということもあったので紹介します。
・カスタムコマンド
同じ作業を何度もお願いする場合はカスタムコマンドがとても便利でした。(プロジェクトのメンバーが用意してくれて私は使っただけです…)
カスタムコマンドはたくさんありましたが、一番使用したものを少しだけ紹介します。
- commit 用のカスタムコマンドサンプル
---
description: 未コミットのファイルを確認し、適切な粒度でコミットを作成する
allowed-tools: [Bash, Read, Edit, TodoWrite]
---
# スマートコミット実行
未コミットのファイルを分析し、論理的に関連する変更を適切な粒度でコミットします。
## 実行手順
1. **作業計画の作成**
- TodoWrite ツールで必要な作業をリスト化
- 品質チェック、コード整理、コミット準備の各ステップを明確化
2. **品質チェック(コミット前必須)**
- プロジェクトで定義されている品質チェックを実行
- 一般的な例:
- Linter/Formatter (ESLint, Prettier, ktlint, rustfmt 等)
- 型チェック (TypeScript, Flow 等)
- テスト実行 (Jest, pytest, JUnit 等)
- 変更に関連するテストがある場合は必ず実行
- **フロントエンド(TypeScript/React)の場合**:
- `pnpm lint` - ESLint チェック
- `pnpm type-check` - TypeScript 型チェック
- `pnpm format:check` - Prettier フォーマットチェック
- `pnpm format` - フォーマット自動修正(pre-commit フックでエラーになる前に実行)
- `pnpm test` - テスト実行(該当する場合)
3. **未コミット状況確認**
- `git status`で変更されたファイルをリスト
- `git diff --stat`で変更の統計情報を確認
- `git diff`で具体的な変更内容を分析
4. **変更内容のグループ化**
- 機能追加、バグ修正、リファクタリング、スタイル修正など論理的に分類
- 関連するファイルをまとめてグループ化
- 不要なデバッグコード・コメントの削除
5. **適切な粒度でコミット**
- 各グループごとに独立したコミットを作成
- Conventional Commits 形式でメッセージ作成
- 日本語で分かりやすい説明を追加
- 1 コミット = 1 つの論理的変更の原則
6. **品質確保**
- プレコミットフックが実行されることを確認
- コミットメッセージ検証が通ることを確認
- 最終的な`git status`でクリーンな状態を確認
7. **プロジェクトメモリ更新検討**
- 作業中に発見した技術的課題・解決方法を CLAUDE.md に追加検討
- 新しいエラーパターン、ライブラリ使用方法、設定の注意点等
- 将来の開発効率化につながる知見の蓄積
## コミットメッセージ形式
```
<type>(<scope>): <subject>
<body>
```
## 実行例
```bash
# TodoWriteで作業計画
1. コードのLint/Format実行
2. 型チェック実行(該当する場合)
3. テスト実行
4. 不要なコメント・デバッグコードの削除
5. git status確認とコミット準備
6. プロジェクトメモリ更新の検討
# 品質チェック
# TypeScript/Reactの場合
cd frontend && pnpm lint
cd frontend && pnpm type-check
cd frontend && pnpm format:check
# フォーマットエラーがある場合は自動修正
cd frontend && pnpm format
cd frontend && pnpm test
✅ すべての品質チェックツールとテストがパス
# コミット作成例
1. feat(auth): ユーザー認証機能を追加
2. fix(api): レスポンスヘッダーの不具合を修正
3. refactor(utils): 共通ユーティリティ関数を整理
4. test: 認証機能のユニットテストを追加
5. docs: APIドキュメントを更新
6. chore: 開発環境の設定ファイルを更新
```
## 注意事項
- **必ず品質チェックとテストを実施**してからコミット
- テストが失敗している場合は、関連するテストか確認し、修正してからコミット
- 変更したコードに対応するテストがある場合は必ず実行
- エラーや警告は可能な限り解消してからコミット
- パスに特殊文字が含まれる場合は適切にエスケープ
- プロジェクト固有のビルドツールやコマンドを確認(Makefile、package.json、build.gradle 等)
**動作を開始します...**
- Pull Request 用のカスタムコマンドサンプル
---
description: Create a pull request for the current branch
allowed-tools: [Bash, Read]
---
# Pull Request 作成
現在のブランチから Pull Request を作成します。
## 実行手順
1. **git status 確認**
- 未コミットの変更確認
- 必要ならコミット作成
2. **ブランチ状態確認**
- 現在のブランチ名確認
- リモートとの同期状態確認
3. **Push 実行**
- `git push -u origin <branch-name>`
4. **PR 作成**
- `gh pr create`で Pull Request 作成
- タイトルと説明を簡潔に記載
## 実行例
```bash
# 状態確認
git status
git branch --show-current
# Push
git push -u origin feature-branch
# PR作成
unset GITHUB_TOKEN && gh pr create --title "feat: 新機能追加" --body "## Summary
- 機能の簡潔な説明
- 変更内容の要点"
```
## 注意事項
- GITHUB_TOKEN 環境変数が設定されている場合は`unset GITHUB_TOKEN`を実行
- gh auth で認証済みであることを確認
**動作を開始します...**
/commit
/pr
など作成したカスタムコマンドのファイル名で実行すると、記載した内容を実行してくれます。
この 2 つはわかりやすく Agent に移譲できる部分で、非常に助かりました。
・コンテキスト枯渇問題/auto-compact
Claude Code を使用しているとよく直面する問題です。
そもそも私が 1 セッションで実行する内容が多すぎることも問題かもしれませんが、compact での Context 圧縮後は必要な情報が失われてしまい、Claude Code が迷走してしまうことがしばしばありました。
これはよく取り上げられる問題でいろいろな解決方法が情報としてありますが、Sub Agentsを利用して、メインセッションでのコンテキストの使用を減らすという方法があります。
たとえば、先ほど記載した commit のカスタムコマンドの場合、品質チェック(lint/type-check/format/test)で結構な Context を使用します。
この部分を Sub Agents に依頼する方法にすると以下のようになります。
- commit カスタムコマンド(Sub Agent 使用)
---
description: 未コミットのファイルを確認し、適切な粒度でコミットを作成する
allowed-tools: [Bash, Read, Edit, TodoWrite]
---
# スマートコミット実行
未コミットファイルを分析し、論理的に関連する変更を適切な粒度でコミットします。
品質チェックとテスト実行はサブエージェントに委譲してコンテキストを節約します。
## 実行手順
1. **作業計画の作成**
- TodoWrite ツールで必要な作業をリスト化
- 品質チェック、コード整理、コミット準備の各ステップを明確化
2. **品質チェック(サブエージェントに依頼)**
```
@frontend-quality-checker を呼び出して品質チェックを実行
- ESLint、Prettier、TypeScript型チェックの結果サマリーを取得
- エラーがある場合は自動修正を依頼
```
3. **未コミット状況確認**
以下省略...
- @frontend-quality-checker
(Sub Agent)
---
name: frontend-quality-checker
description: Frontend(TypeScript/React)のコード品質チェックを効率的に実行
tools: [Bash, Read, Edit]
---
# Frontend 品質チェック専門エージェント
あなたはFrontendコード品質チェックの専門家です。
ESLint、Prettier、TypeScript型チェック、CSS/Stylelintを効率的に実行し、結果を簡潔にまとめます。
## 責務
1. パッケージマネージャーの自動判定(npm/yarn/pnpm)
2. 適切な品質チェックツールの実行
3. 自動修正可能な問題の修正
4. 結果の簡潔なサマリー作成
## 実行プロセス
### 1. プロジェクト構成の確認
```bash
# パッケージマネージャーの判定
if [ -f "pnpm-lock.yaml" ]; then
PKG_MANAGER="pnpm"
elif [ -f "yarn.lock" ]; then
PKG_MANAGER="yarn"
elif [ -f "package-lock.json" ]; then
PKG_MANAGER="npm"
else
echo "No package manager lock file found"
PKG_MANAGER="npm"
fi
# 利用可能なスクリプトの確認
cat package.json | grep -A 20 '"scripts"'
```
### 2. ESLint実行(自動修正付き)
```bash
# ESLintの実行
$PKG_MANAGER run lint --fix 2>/dev/null || \
$PKG_MANAGER run eslint . --ext .ts,.tsx,.js,.jsx --fix 2>/dev/null || \
npx eslint . --ext .ts,.tsx,.js,.jsx --fix
# 修正できなかったエラーのみ報告
$PKG_MANAGER run lint 2>&1 | grep -E "error|warning" | head -10
```
### 3. Prettier実行(フォーマット)
```bash
# Prettierでフォーマット
$PKG_MANAGER run format 2>/dev/null || \
$PKG_MANAGER run prettier --write "src/**/*.{ts,tsx,js,jsx,css,scss}" 2>/dev/null || \
npx prettier --write "src/**/*.{ts,tsx,js,jsx,css,scss}"
# フォーマット対象ファイルの確認
$PKG_MANAGER run format:check 2>/dev/null || \
npx prettier --check "src/**/*.{ts,tsx,js,jsx,css,scss}" 2>&1 | grep -c "Code style issues"
```
### 4. TypeScript型チェック
```bash
# TypeScriptコンパイラチェック
$PKG_MANAGER run type-check 2>/dev/null || \
$PKG_MANAGER run tsc --noEmit 2>/dev/null || \
npx tsc --noEmit
# エラーがある場合は主要なものを抽出
npx tsc --noEmit 2>&1 | grep -E "error TS" | head -5
```
### 5. CSS/Stylelint(使用している場合)
```bash
# Stylelintが設定されている場合
if [ -f ".stylelintrc" ] || [ -f ".stylelintrc.json" ] || [ -f "stylelint.config.js" ]; then
$PKG_MANAGER run stylelint "src/**/*.{css,scss}" --fix 2>/dev/null || \
npx stylelint "src/**/*.{css,scss}" --fix
fi
```
### 6. 不要なコードの検出
```bash
# console.logの検出
grep -r "console\." src/ --include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js" | grep -v "// eslint-disable" | head -5
# debugger文の検出
grep -r "debugger" src/ --include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js" | head -5
# TODO/FIXMEコメントの検出(参考情報)
grep -r "TODO\|FIXME" src/ --include="*.tsx" --include="*.ts" | head -3
```
## 出力形式
### 成功時:
```
✅ Frontend品質チェック完了
📝 ESLint:
- Status: PASS
- 自動修正: 12件(未使用import削除、セミコロン追加等)
💅 Prettier:
- Status: PASS
- フォーマット: 8ファイル
📘 TypeScript:
- Status: PASS
- 型エラー: 0件
🎨 Stylelint:
- Status: PASS
- 修正: 3ファイル(順序統一、ベンダープレフィックス)
🔍 コード品質:
- console.log: 0件
- debugger: 0件
- TODO: 2件(参考)
```
### エラーがある場合:
```
⚠️ Frontend品質チェック完了(要対応事項あり)
📝 ESLint:
- Status: FAIL
- 自動修正済: 8件
- 要手動修正: 3件
• src/components/Button.tsx(12:5): 'onClick' is defined but never used
• src/hooks/useAuth.ts(45:10): React Hook "useEffect" has missing dependencies
• src/pages/Dashboard.tsx(78:3): Unexpected console.log
💅 Prettier:
- Status: PASS
- フォーマット完了: 12ファイル
📘 TypeScript:
- Status: FAIL
- 型エラー: 2件
• src/types/user.ts(15:3): Property 'email' is missing in type 'User'
• src/api/client.ts(28:7): Type 'string' is not assignable to type 'number'
🔍 コード品質:
- console.log: 3件検出(削除推奨)
- debugger: 1件検出(必ず削除)
```
## パフォーマンス最適化
### 変更ファイルのみチェック
```bash
# 変更されたファイルのみをチェック
CHANGED_FILES=$(git diff --name-only --diff-filter=ACMR | grep -E "\.(tsx?|jsx?|css|scss)$")
if [ ! -z "$CHANGED_FILES" ]; then
# ESLint
npx eslint $CHANGED_FILES --fix
# Prettier
npx prettier --write $CHANGED_FILES
# TypeScript(プロジェクト全体のチェックが必要)
npx tsc --noEmit
fi
```
### キャッシュの活用
```bash
# ESLintキャッシュを使用
$PKG_MANAGER run lint --cache --cache-location node_modules/.cache/eslint/
# Prettierキャッシュを使用
$PKG_MANAGER run prettier --cache --write "src/**/*.{ts,tsx}"
```
## エラー処理
- ツールがインストールされていない場合は、該当チェックをスキップして報告
- package.jsonのscriptsを優先的に使用
- エラーは最大5件まで報告(冗長さを避ける)
- 自動修正可能なものは全て修正してから報告
メインエージェントには簡潔なサマリーのみ返し、詳細なエラーログは要求された場合のみ共有します。
これにより、品質チェック(lint/type-check/format)などの処理は、メインセッションのコンテキストを圧迫することなく実行できます。
さらに Sub Agent は、単にコンテキストを節約するための手段にとどまらず、タスクを役割ごとに分担・明確化することで、処理の品質や再現性を高められるという大きな利点もあります。
たとえば、仕様調査・コードの要約・リファクタリング・ドキュメント作成・レビューといった作業を、目的に応じたエージェントに任せることで、それぞれのタスクに特化した最適な対応が可能になります。
こうした「エージェントによる分業スタイル」は、個人開発だけでなく、今後のチーム開発や継続的なプロジェクト運用においても、有効なアプローチになると感じました。
・MCP
- Serena
Claude Code などの LLM エージェントと連携し、シンボル単位でのコード探索・編集を可能にする MCP ツールです。
一時期発生した「Claude Code がバカになった問題」がきっかけで導入しました。
曖昧な grep 的検索ではなく、関数・変数・クラスなどのシンボル単位でコード構造を認識し、セマンティックに探索・編集ができるため、Claude Code が効率よく対象コードを扱えるようになります。
- Context7
最新の公式ドキュメントやコード例を LLM が自動取得・参照できる MCP です。 役割としてはとてもシンプルですが、実はかなり重要なユースケースをカバーしてくれます。
実際に私のプロジェクトでも、特定のライブラリでうまく実装ができず、Claude Code でも全く解決できずに迷走したことがありました。 その理由は、ライブラリのメジャーバージョンが上がっていたのに、Claude Code は一つ前の情報を前提に実装を試みていたためでした。
Context7 を使うことで、「今このバージョンでは何が正解か?」をエージェントが正確に把握した上で実装できるようになるため、再現性や信頼性が大きく向上しました。
ほんとにおわりに
以上です!補足のほうが長くなってしまいました。
まだまだ模索中の段階ではありますが、こうした試行錯誤を通して、自分なりの「AI との開発スタイル」が少しずつ見えてきたように思います。 今後も学びながら、社内外の仲間と知見を共有し、 より良い“AI 時代のエンジニアリング” を一緒に築いていけたら嬉しいです!