Claude Code入門:実践ガイド
先週、私はプロダクションのバグと格闘するのに3時間を費やしました。スタックトレースは深くネストされた非同期関数を指しており、まるで探偵が虫眼鏡で調べるかのように、一つ一つのawaitを手作業で追跡していました。最終的には修正できましたが、この一連の出来事で私は考えました:なぜ一人でやっているんだ? それがきっかけで、Claude Codeを単なるおもちゃとしてではなく、真のペアプログラマーとして適切に学ぼうと決心しました。
以下は、1週間の集中的な使用後にわかったことです。うまくいかなかった点と、私が見つけた回避策も含めています。
Claude Codeとは何か(そして何でないか)
Claude Codeは、Anthropicが提供するターミナルベースのAIコーディングアシスタントです。コード行を自動補完するVS Code拡張機能ではありません。ターミナル上で動作し、プロジェクト全体のコンテキストを読み取り、シェルコマンドの実行、ファイルの編集、コードベースの推論が可能なCLIツールです。コードのすべての行を読み、任意のコマンドを実行できるが、明確な指示と時折のサポートを必要とするジュニアエンジニアのようなものだと考えてください。
約15,000ファイルのNext.jsプロジェクト(アプリ、パッケージ、デザインシステムを含むモノレポ)でテストしました。コンテキストの処理は驚くほど良好でしたが、大規模なリファクタリングで2回トークン制限に達しました。
インストール:30秒で完了
npm install -g @anthropic-ai/claude-code
# または
yarn global add @anthropic-ai/claude-code
次に認証します:
claude login
ブラウザウィンドウが開きます。APIキーを貼り付けてください(console.anthropic.comから取得)。完了です。
プロのヒント: チームで作業する場合、シェルプロファイルにANTHROPIC_API_KEYをエクスポートしておくと、個別にログインする必要がなくなります。direnvユーザーは.envrcに設定しています。
最初のセッション:「説明して」コマンド
最も過小評価されている機能は/explainです。私は数週間悩まされていたファイルから始めました:
cd ~/projects/my-app
claude
# これでインタラクティブREPLが起動
次のように入力しました:
/explain src/utils/data-transformer.ts
Claudeはファイル全体(約400行)を読み、3つの主要関数、データフロー、そして重要なことに、気づいていなかった競合状態を簡潔に説明してくれました。Promise.allの呼び出しが共有のミュータブル配列を使用していたのです。修正案も提示してくれました:
// 修正前:
const results = [];
for (const item of items) {
results.push(processItem(item));
}
return Promise.all(results).then(() => results);
// 提案された修正:
const results = await Promise.all(items.map(processItem));
return results;
この一回のやり取りで、デバッグセッションが不要になりました。/explainコマンドだけで導入する価値があります。
「編集して」ワークフロー:真価を発揮する場面
試行錯誤の末に確立した実践的なワークフローは次のとおりです:
- 自然言語で問題を説明する – ファイルと変更内容を具体的に指定
- Claudeに編集を提案させる – diffが表示される
- diffをレビューする – 信頼していても必ず確認
- 承認または拒否する – 変更ごとにyes/no
セッション例:
> src/components/UserCard.tsxで、ローディング状態をスピナーからスケルトンに変更してください。ui/skeletonの既存のSkeletonコンポーネントを使用してください。
Claudeの応答:
UserCard.tsxとSkeletonコンポーネントを読んで、現在の実装を理解します。
[ファイルを読み込み]
以下が提案する変更です:
- {loading && <Spinner className="h-8 w-8" />}
+ {loading && <Skeleton className="h-8 w-8 rounded-full" />}
また、エラー状態にはテキストだけでなく再試行ボタンを表示すべきです。それも追加しましょうか?
「はい」と答えると、適切なクリックハンドラ付きのボタンが追加されました。所要時間:45秒。手動で行うと4分とコンテキストスイッチの時間がかかります。
「バグを修正して」フロー:実例
Reactコンポーネントが無限に再レンダリングされるバグがありました。スタックトレースはuseEffectの依存配列を指していました。エラーを貼り付けました:
> ProfilePage.tsxで「Maximum update depth exceeded」エラーが発生しています。42行目のuseEffectが原因のようです。
Claudeがファイルを読んで言いました:
問題は44行目です:依存関係として`user.profile`を使用していますが、`user`はレンダリングのたびに新しいオブジェクト参照になります。useEffectが状態を設定し、それが再レンダリングを引き起こし、新しい`user`オブジェクトが作成され、再びエフェクトがトリガーされます。
修正:代わりに`user.profile.id`を依存関係として使用するか、userオブジェクトをメモ化してください。
そして修正を書いてくれました:
useEffect(() => {
fetchProfile(user.profile.id);
}, [user.profile.id]); // [user.profile]から変更
これは完璧に機能しました。ただし、注意点があります:Claudeはuser.profileがundefinedになる可能性をチェックしませんでした。レビューでそれに気づき、オプショナルチェーンを自分で追加しました。常に出力をレビューしてください。
「リファクタリングして」コマンド:強力だが危険
有機的に成長した200行のユーティリティファイルでClaudeのリファクタリングを試しました。プロンプト:
> src/utils/format.tsを、ネストされたif-elseの代わりに関数型パイプラインを使用するようにリファクタリングしてください。同じ公開APIを維持してください。
Claudeはlodash/fpのpipeを使用したクリーンなパイプラインを提案しました:
export const formatDisplayName = pipe(
trim,
capitalize,
truncate(50),
addEllipsis
);
美しいです。しかし、内部のヘルパー関数の名前も変更しました(truncate → truncateString)。名前が曖昧だと考えたためです。その変更により、その関数をインポートしていた他の3つのファイルが壊れました。教訓: リファクタリングのプロンプトには常に「エクスポートされた関数名やシグネチャを変更しないでください」と追加しましょう。
「コマンドを実行して」機能:隠れた宝石
Claudeはターミナルコマンドを実行できます。これは以下の場合に非常に便利です:
- テストの実行と失敗の解析
- 依存関係のインストール
- Git履歴の確認
例:
> authモジュールのテストを実行して、失敗があれば表示してください
npm test -- --testPathPattern=authを実行し、出力を解析して、どのテストがなぜ失敗したかを正確に表示しました。修正案も提案してくれました:
34行目のテストは{ status: 200 }を期待していますが、APIは{ statusCode: 200 }を返しています。
テストを更新しますか、それともAPIの応答を変更しますか?
「ドキュメントを書いて」機能:実際に優秀
複雑な関数のJSDocが必要でした。Claudeがパラメータの説明、戻り値の型、使用例まで含めて書いてくれました:
/**
* 生のAPI応答を正規化されたストア構造に変換します。
* ページネーションメタデータとエラー正規化を処理します。
*
* @param response - 生のfetch応答オブジェクト
* @param schema - 正規化スキーマ(schemas/から)
* @returns 正規化されたエンティティマップと結果ID
*
* @example
* const { entities, result } = normalizeResponse(
* await fetch('/api/users'),
* userSchema
* );
*/
元のコードで「normalization」のスペルを間違えていたことにも気づきました。恥ずかしいですが、助かりました。
うまくいかなかった点(と回避策)
1. 大規模ファイルのトークン制限
Claudeのコンテキストは最大約20万トークンです。私のモノレポのpackage.jsonだけで8万トークンありました。リファクタリング中に2回制限に達しました。
修正: /compactコマンドを使用して議論を要約する。または、フォーカスしたプロンプトでセッションを再開する:「src/utils/format.tsのリファクタリングを続けてください。ネストされたif-elseを関数型パイプラインに変換していました。」
2. 幻覚のファイルパス
2回、存在しないファイルへの編集をClaudeが提案しました。実際のファイルがsrc/lib/helpers.tsであるのに、src/utils/helpers.tsというファイルを作り出しました。
修正: 変更を許可する前に、必ず「最初に編集が必要なファイルをリストアップしてください」と依頼し、各パスの存在を確認する。
3. 過度に楽観的なリファクタリング
Claudeは「可読性のために」動作中のforループを再帰関数に置き換えることを提案しました。再帰版はエレガントでしたが、大規模な配列ではスタックオーバーフローのリスクがありました。
修正: 「反復的な解決策を再帰より優先する」や「O(n)時間計算量を維持する」などの制約を追加する。
苦労して学んだ実践的なヒント
1. 最初に/initコマンドを使用する
新しいプロジェクトで開始する場合:
> /init
これにより、Claudeがpackage.json、tsconfig.json、.eslintrcなどの設定ファイルを読み取ります。プロジェクトの規約を理解するようになります。これがないと、セットアップと競合するPrettierの書式を提案する可能性があります。
2. セッションの焦点を絞る
各セッションは1つの目標を持つべきです。「認証バグを修正する」であって「コードベースを改善する」ではありません。30分を超えるセッションは、コンテキストが蓄積されるにつれて品質が低下することがわかりました。
3. デバッグには--verboseフラグを使用する
claude --verbose
APIに送信される正確なプロンプトが表示されます。Claudeが混乱しているように見える場合に便利です—指示が誤って解釈されたかどうかを確認できます。
4. --modelフラグが重要
claude --model claude-3-5-sonnet-20241022
デフォルトのモデルも優れていますが、コード生成にはSonnet 3.5、簡単な説明にはHaikuの方が適していることがわかりました。試してみてください。
1週間後の評価
Claude Codeは、コードベースの理解に代わるものではありません。開発の退屈で反復的な部分の力を増幅するものです。最初の1週間で約4時間節約できたと見積もっています—主にドキュメント、Stack Overflow、エディタ間のコンテキストスイッチが不要になったためです。
しかし、魔法ではありません。パスを幻覚し、過度に最適化し、意図を誤解することがあります。有能なインターンとして扱ってください:明確な指示を与え、作業をレビューし、本番環境の認証情報を決して信頼しないでください。
次のステップ
大規模なリファクタリングから始めないでください。もっとよく理解したいと思っていたファイルで/explainから始めてください。次に、小さなバグを1つ修正してみてください。そして、単体テストを1つ追加してください。
本当のスキルはClaude Codeを使用することではなく、いつ使用するかを知ることです。退屈な作業に使用してください。難しい問題のために頭脳を温存してください。