難易度:中級 | 所要時間:25 分 | 得られるもの:ソースコード級の 7 つの節約テクニックを習得し、API 請求を 30-60% も減額
対象読者のイメージ
現在 Claude Code を使っている、または深く使い込もうとしているフルスタックエンジニア。特に API コスト管理に関心の高い個人開発者や小規模チームを想定しています。もし Claude Code の理解が「入れて使うだけ」の段階で止まっているなら、この記事でその裏にどれだけ調整可能なパラメータが隠れているかがわかります。
主要な依存関係と環境
- Node.js 18+
- Claude Code 2.1.88
- TypeScript の基礎(型定義が読めればOK)
- npm または pnpm
- 有効な ANTHROPIC_API_KEY
TIP
この記事のすべてのソースコード例は 2.1.88 バージョンに基づいています。バージョン確認方法:claude --version。バージョンによってソースの細部は多少異なる可能性がありますが、核となる仕組みは同じです。
完全なプロジェクト構造ツリー
# Claude Code のソースコード構造(関連ディレクトリ)
src/
├── cost-tracker.ts # コスト追跡の中核
├── costHook.ts # コスト出力用 Hook
├── Tool.ts # ツール抽象ファクトリ
├── tools.ts # ツール登録とフィルタリング
├── tools/
│ ├── BashTool/ # シェル実行ツール
│ │ └── BashTool.tsx
│ │ └── readOnlyValidation.ts # 読み取り専用の検出ロジック
│ ├── FileReadTool/ # ファイル読み取り
│ ├── FileEditTool/ # ファイル編集
│ └── ...
├── services/
│ ├── compact/ # コンテキスト圧縮サービス
│ │ └── compact.ts
│ └── tools/
│ └── toolOrchestration.ts # ツール並列実行の分割
├── skills/
│ └── loadSkillsDir.ts # スキルの読み込み
├── types/
│ └── permissions.ts # 権限モード定義
├── upstreamproxy/ # 上流プロキシ(企業向け)
│ ├── upstreamproxy.ts
│ └── relay.ts
└── utils/
└── git.ts # Git / Worktree ツール
一、Claude Code の請求がどうして高くなるのか
節約の話をする前に、まずお金がどこで消えているのかを整理します。Claude Code の API 請求は主に次の 3 つによって左右されます。
1. コンテキストのトークン総量
会話のたびに Claude Code は、過去メッセージ、ツール呼び出し結果、ファイル内容をまとめて API に送ります。コンテキストが大きくなるほど、1 リクエストあたりの単価は上がります。cost-tracker.ts では、各 session の消費を正確に追跡しています。
// src/cost-tracker.ts
interface ModelUsage {
inputTokens: number;
outputTokens: number;
cacheReadInputTokens: number; // キャッシュヒット(より安い)
cacheCreationInputTokens: number; // キャッシュ作成(一時費用)
webSearchRequests: number;
costUSD: number;
}
ここで重要なのは 2 点です。cacheReadInputTokens は通常の input token より約 10 倍安く、cacheCreationInputTokens はキャッシュ作成時の一度きりの手数料です——この違いが、後述する圧縮戦略を直接左右します。
2. ツール呼び出しの頻度
Claude Code は平均して 1 会話で数十回のツール呼び出しを発生させます。ツール呼び出しのたびに API リクエストが 1 回発生します(ストリーミング tool use)。ツールが多いほど、呼び出し頻度が高いほど、コンテキストはより速く膨らみます。
3. Agent の並列数
AgentTool でサブ Agent を起動したり、Coordinator モードで複数の Worker を同時にスケジューリングしたりすると、毎回それぞれ独立したセッションになります——結果としてコストがそのまま 2 倍に。
Claude Code には cost-tracker.ts が内蔵されており、これらの消費をリアルタイムで追跡します。プロセス終了時にはデータをプロジェクト設定に永続化します。
// src/costHook.ts
// プロセス終了時に自動保存し、請求サマリーを出力
process.on('exit', () => {
if (hasConsoleBillingAccess()) {
console.log(formatTotalCost()); // per-model の内訳つきで請求を出力
}
saveCurrentSessionCosts(getFpsMetrics?.());
});
WARNING
請求の追跡はプロジェクト単位で隔離されます——異なるディレクトリの session 消費は合算されません。複数のプロジェクトで Claude Code を使っている場合、各プロジェクトに独立したコスト記録があります。
二、節約テクニック 1:Compact によるコンテキスト圧縮で 30-50% 節約
Claude Code には compact サービスがあり、過去の会話を「圧縮」して要約に変換し、コンテキストを適正な規模に保ちます。ソースコード内の重要パラメータは一目でわかります。
// src/services/compact/compact.ts
const POST_COMPACT_TOKEN_BUDGET = 50_000; // 圧縮後の総トークン上限
const POST_COMPACT_MAX_TOKENS_PER_FILE = 5_000; // 1 ファイルあたり最大 5K トークン
const POST_COMPACT_MAX_TOKENS_PER_SKILL = 5_000; // 1 つの Skill あたり最大 5K トークン
const POST_COMPACT_SKILLS_TOKEN_BUDGET = 25_000; // Skill 合計で 25K 上限
const POST_COMPACT_MAX_FILES_TO_RESTORE = 5; // 圧縮後に最大で 5 ファイルまで復元
圧縮の流れは 3 ステップです:トリガー → API 要約 → 重要なファイルの再付与。まず pre_compact hooks を発火し、圧縮 API を呼び出します(これは別枠の API リクエスト 1 回)。次に post_compact hooks を発火し、最後に最近読んだファイルを再び attach します。
実戦テク: トリガーの閾値を調整すれば、圧縮頻度を制御でき、ひいてはコストをコントロールできます。
// settings.json — プロジェクトルートの .claude/ の下
{
"compact": {
"autoCompactThreshold": 0.85 // コンテキスト使用率が 85% になったら圧縮を実行(デフォルト)
}
}
閾値を下げる(たとえば 0.7)と圧縮がより頻繁になり、毎回の圧縮コストは小さくなりますが、要約の品質がわずかに下がる可能性があります。逆に閾値を上げる(0.95)とその反対です。
TIP
長い会話の後半で Claude Code が「物忘れ」のようになるなら、圧縮後に重要なコンテキストが切り落とされた可能性が高いです。この場合は、会話内で重要情報を手動で補うか、autoCompactThreshold を下げて圧縮をより頻繁にしつつ、毎回の圧縮量を小さくすると効果的です。
三、節約テクニック 2:Read-only ツールをうまく見極めて無駄を回避
Claude Code の各ツールには isReadOnly() メソッドがあり、ツールが副作用を持つかどうかを判定します。ツールのスケジューラはこのフラグに基づいて、並列実行を許可するかを決めます。
// src/Tool.ts — ツールはデフォルトで保守的(fail-closed)
const TOOL_DEFAULTS = {
isConcurrencySafe: (_input) => false, // デフォルトで安全ではないため並列しない
isReadOnly: (_input) => false, // デフォルトで副作用あり
isDestructive: (_input) => false, // デフォルトで破壊的ではない
};
肝は BashTool です。ここには、コマンド分類の詳細ロジックが内蔵されています。
// src/tools/BashTool/BashTool.tsx
// 読み取り専用コマンドのホワイトリスト — これらは安全に並列実行でき、状態を変更しません
const BASH_SEARCH_COMMANDS = ['find', 'grep', 'rg', 'ag', 'ack', 'locate', 'which', 'whereis'];
const BASH_READ_COMMANDS = ['cat', 'head', 'tail', 'less', 'more', 'wc', 'stat', 'file', 'strings', 'jq', 'awk', 'cut', 'sort', 'uniq', 'tr'];
const BASH_LIST_COMMANDS = ['ls', 'tree', 'du'];
const BASH_SEMANTIC_NEUTRAL_COMMANDS = ['echo', 'printf', 'true', 'false', ':'];
実戦テク: たとえば ls -la でディレクトリ構造を問い合わせると、Claude Code はこれを読み取り専用の操作だと理解し、他の読み取り専用操作とまとめて並列実行してくれます。待ち時間が減るわけです。逆に rm -rf node_modules を実行すると、破壊的操作として認識され、直列(シリアル)処理が強制されます。毎回確認が必要になるので注意です。
このロジックを理解したら、自分のコマンドを意図的に組み立てて、より良い並列最適化を引き起こせます。
# 良い例:読み取り専用操作は 1 つのコマンド内で組み合わせ、ツール呼び出し回数を減らす
find . -name "*.ts" | head -20 && wc -l src/**/*.ts
# 悪い例:破壊的操作を読み取り専用コマンドに混ぜる
find . -name "*.log" && rm -rf logs/ # この場合は直列でブロックされる
四、節約テクニック 3:Skills システムで繰り返し Prompt を削減し、Prompt Token を節約
Claude Code は Skills のスキルシステムをサポートしています。これは本質的に、再利用できる prompt の断片の集合です。プロジェクトのルートに skills/ フォルダを作り、中に Markdown ファイルを置くと、Claude Code が自動的にそれらを読み込みます。
your-project/
└── skills/
└── my-workflow/
└── SKILL.md # ディレクトリ形式:skill-name/SKILL.md
Skill ファイルには frontmatter のメタデータがあります。
---
name: my-skill
description: React コンポーネントのリファクタリング標準フロー
whenToUse: コンポーネントのリファクタリングや大規模コンポーネントの分割が必要なとき
paths: ["src/**/*.tsx", "src/**/*.ts"] # これらのパスに一致したときのみ有効化
allowedTools: [Read, Edit, Bash] # 使用可能ツールを制限
arguments: [filePath, scope]
executionContext: inline # inline または fork
---
# Skill の本文 — ここに標準のリファクタリング手順プロンプトを書く
なぜ節約できる? 新しい会話を作るたびに、Claude Code は system prompt の中へ、すべてのツール説明、ルール、コンテキストを詰め込む必要があります。Skills によってよくあるワークフローを標準化すると、毎回同じ指示を繰り返して入力するための Token 消費が減ります。節約できるのは、主にあなたが手動でコピペしていた prompt の長さです。
paths フィールドが条件の有効化のカギです——指定したパスに一致したときにだけ、その Skill が候補リストに登場します。関係のない Skill がコンテキストを汚すのを防げます。
// src/skills/loadSkillsDir.ts
// 条件付き有効化:gitignore 風のマッチング
activateConditionalSkillsForPaths(filePaths, cwd) {
// src/**/*.tsx ファイルにアクセスした後、React 関連の Skills が有効化される
}
TIP
再利用率が高い Skill は ~/.claude/skills/(ユーザー単位)に置くのがおすすめです。プロジェクト単位の Skill はプロジェクト固有のフローだけを置きましょう。階層が上ほど影響範囲が広く、節約効果もより大きくなります。
五、節約テクニック 4:並列分割でリトライを減らし、Rate Limit の消費を節約
Claude Code は、すべてのツール呼び出しを直列に実行するわけではありません。賢い分割器が「同時に走らせてもよい」ツールを 1 つの組にまとめ、「待ち行列が必要」なツールは別で処理します。
// src/services/tools/toolOrchestration.ts
// 並列上限を読み取り(デフォルトは 10)
function getMaxToolUseConcurrency() {
return parseInt(process.env.CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY ?? '10', 10);
}
// ツールの分割:連続的に読み取り専用なら結合、それ以外は新しいバッチ
function partitionToolCalls(toolUseMessages, toolUseContext): Batch[] {
return toolUseMessages.reduce((acc, toolUse) => {
const isConcurrencySafe = tool.isConcurrencySafe(parsedInput.data);
if (isConcurrencySafe && acc[acc.length-1]?.isConcurrencySafe) {
acc[acc.length-1].blocks.push(toolUse); // 並列安全なので結合
} else {
acc.push({ isConcurrencySafe, blocks: [toolUse] }); // 新しいバッチ
}
return acc;
}, []);
}
実戦テク: あなたの MCP ツールが並列をサポートできるなら、定義時に必ず isConcurrencySafe: true を明示してください。宣言していないツールはデフォルトで直列になります。そして直列ツールが Rate Limit に当たってリトライすると、Token が無駄に消えるのが“見えにくい”形で発生しますが、累積するとかなり大きいです。
// settings.json — MCP ツールに並列安全を宣言
{
"mcpServers": {
"my-mcp": {
"command": "npx",
"args": ["-y", "my-mcp-tool"],
"isConcurrencySafe": true // 宣言することで他の読み取り専用ツールと並列実行できる
}
}
}
並列上限は環境変数で引き上げることもできます。
# マシン性能が高く、API 枠が十分なときに推奨
export CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY=20
六、節約テクニック 5:Worktree で全クローンの代わりに隔離し、協業コンテキストを軽量化
Claude Code は Worktree を内蔵サポートしています。Git Worktree は同じリポジトリ内で複数ブランチを別ディレクトリにチェックアウトできます。クローンを複数作る必要はありません。Claude Code の findCanonicalGitRoot は Worktree のパスを自動で解析します。
// src/utils/git.ts
// Worktree のルートを安全に解決
function resolveCanonicalRoot(gitRoot: string): string {
const gitDirContent = readFileSync(path.join(gitRoot, '.git'), 'utf8');
// .git ファイル形式: gitdir: /path/to/.git/worktrees/<name>
const commonDir = extractCommonDir(gitDirContent);
// 安全な検証:worktreeGitDir は commonDir/worktrees/ のサブディレクトリでなければならない
// 悪意あるリポジトリが .git ファイルで sandbox escape を試みないように防ぐ
validateWorktreeSecurity(worktreeGitDir, commonDir);
return mainRepoRoot;
}
節約の原理: チームで「機能ブランチごとにリポジトリを 1 つずつクローンする」運用だと、各クローンの .git ディレクトリ(数 GB になる可能性)が Claude Code のコンテキストスキャン範囲に入ってしまいます。Worktree モードでは .git は基本的に 1 つだけなので、スキャンするコンテキストのボリュームが大幅に縮小されます。
# クローンではなく Worktree を作成
git worktree add ../feature-sidebar feature/sidebar
# Claude Code は Worktree を自動認識し、メインのリポジトリのコンテキストを共有
# 別の worktree に切り替えるときは、そのディレクトリへ cd してそのまま claude を起動
cd ../feature-sidebar && claude
WARNING
Worktree のセキュリティ機構が重要です:Claude Code は .git ファイルのパスが sandbox escape に悪用されないことを検証します。しかし、信頼できないリポジトリで Worktree を使う場合でも、念のため確認することをおすすめします。
七、節約テクニック 6:Permission モードの調整で確認インタラクションを減らす
Claude Code には完全な権限システムがあり、5 つのモードが「いつあなたに確認が必要か」を決めます。
// src/types/permissions.ts
type PermissionMode =
| 'acceptEdits' // 編集を自動的に承認
| 'bypassPermissions' // 権限チェックを完全にスキップ(危険だが最速)
| 'default' // ルールに従って確認
| 'dontAsk' // 一切確認しない
| 'plan' // Plan モード
| 'auto'; // AI が自動で分類して判断(TRANSCRIPT_CLASSIFIER が有効な場合)
| モード | 挙動 | 速度 | 安全性 |
|---|---|---|---|
default | ルールに従って確認 | 遅い | 安全 |
auto | AI 分類器が自動で判断 | 中 | 比較的安全 |
dontAsk | 確認せずに即実行 | 速い | リスクは自己負担 |
bypassPermissions | チェックを完全スキップ | 最速 | 高リスク |
plan | Plan モードでは実行しない | 最遅 | 最も安全 |
実戦テク: 自分が完全に信頼しているディレクトリ(自分のプロジェクト、コードはすでに git に入っている)なら、settings.json で細かく設定できます。
// ~/.claude/settings.json(ユーザー級)または .claude/settings.json(プロジェクト級)
{
"permissions": {
"defaultMode": "auto",
"allow": [
{ "toolName": "Bash", "ruleContent": "pnpm*" },
{ "toolName": "Read" },
{ "toolName": "Glob" },
{ "toolName": "Grep" }
],
"deny": [
{ "toolName": "Bash", "ruleContent": "rm -rf /" }
],
"ask": [
{ "toolName": "Bash", "ruleContent": "git push" }
]
}
}
auto モードは、手間と安全のバランスがよい省力策です。AI 分類器で操作が安全かどうかを判定し、不必要なポップアップを避けます。確認インタラクションが 1 回減るたびに、コンテキスト切り替えの Token 消費も 1 回分減ります。
WARNING
bypassPermissions モードは Claude Code を root 権限のスクリプトのように扱うのと同じです——入力されたものはすべてそのまま実行されます。隔離されたテスト用ディレクトリでのみ使ってください。メインプロジェクトで有効化するのは絶対にやめましょう。
八、節約テクニック 7:企業向け上流プロキシのキャッシュで、重複 API 呼び出しを減らす
Claude Code の upstreamproxy モジュールは Claude Code Connect(CCR、企業版)向けにプロキシルーティングを提供します。ソースコード内で注目すべきなのが NO_PROXY_LIST の値です。
// src/upstreamproxy/upstreamproxy.ts
const NO_PROXY_LIST = [
'localhost', '127.0.0.1', '::1',
'169.254.0.0/16', '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16',
'anthropic.com', 'github.com', '*.github.com',
// npm / PyPI / Rust レジストリはすべてホワイトリスト対象で、プロキシを通す必要なし
'registry.npmjs.org', 'pypi.org', 'files.pythonhosted.org',
'index.crates.io', 'proxy.golang.org'
];
実戦テク: 企業版でなくても、このロジックを理解しておくとローカル設定を最適化できます。会社のネットワーク内なら、Claude Code は自動的に企業用プロキシへトラフィックをルーティングします。プロキシ層で Token のキャッシュや再利用ができる——これが CCR 企業ユーザーが節約できるための土台となる仕組みです。
自前で MCP サービスを立てる場合は、MCP 側の設定でレスポンスキャッシュを有効化できます。
// settings.json
{
"mcpServers": {
"local-knowledge": {
"command": "node",
"args": ["server.js"],
"env": {
"MCP_CACHE_TTL": "3600" // キャッシュ 1 時間、重複 API 呼び出しを減らす
}
}
}
}
九、よくある問題の切り分け
Q1: 1 行しか変えていないのに、請求がまだ高い?
Claude Code の請求が高い原因が編集操作とは限りません。多くの場合「コンテキストの膨張」が原因です。長い会話の中で 1 行しか変えていなくても、圧縮される前の履歴メッセージやツール結果がコンテキストに残り続けます。確認方法:session 終了時に formatTotalCost() が出す inputTokens を見て、outputTokens と比較してください。inputTokens が大きいほどコンテキストが過剰に膨らんでいるサインです。
Q2: Compact の後、回答の品質が明らかに落ちた?
これは圧縮粒度の問題です。autoCompactThreshold をデフォルトの 0.85 から 0.95 に上げ、圧縮頻度を下げます。その上で、重要な設計判断やコンテキスト情報が会話の早い段階で明確に記録されるようにしておけば、圧縮された要約の品質は上げられます。
Q3: bypass モードは結局安全なの?
安全ではありませんが、隔離された環境なら制御できます。どうしても bypass を使う必要がある場合は、permissions.deny で受けを作ることをおすすめします。
{
"permissions": {
"defaultMode": "bypassPermissions",
"deny": [
{ "toolName": "Bash", "ruleContent": "sudo*" },
{ "toolName": "Bash", "ruleContent": "curl*|wget*" }
]
}
}
Q4: 毎日の Token 消費をどう監視する?
Claude Code は session を終了するたびに自動で請求を出力します(consoleBillingAccess を有効にしている場合)。よりシステム的な方法としては、プロジェクト単位で追跡スクリプトを作ることです。
# プロジェクトの .git/hooks/ に post-checkout フックを追加して記録
# ただ、より実用的なのは .claude/cost/<session-id>.json を直接見ること
Q5: Skills は毎回追加の Token を消費する?
します。ただし制御可能です。Skill の内容が占める Token は POST_COMPACT_SKILLS_TOKEN_BUDGET(25K 上限)に含まれます。Skill が多く、詳細であるほどコンテキストは大きくなるため、Skill を書くときの原則は:精密にマッチさせ、必要最小限の情報だけ。関連するファイルにアクセスしたときだけ Skill を読み込むために、paths フィールドを活用しましょう。
Q6: Worktree を使うと Claude Code の挙動がおかしい?
Worktree には安全な検証メカニズムがあります。.git ファイルの形式が標準でない場合、Claude Code は現在のディレクトリにフォールバックします。.git ファイルの中身が gitdir: /absolute/path/to/.git/worktrees/<name> の形式になっているか確認してください。
十、拡張読書 / 次のステップ
1. 自分の Skill を書いて、繰り返しの工数を減らす
複数のプロジェクトで「このスタイル規約に従ってコードを書いて」系の prompt を何度も書いていると気づいたら、それを Skill に切り出し、~/.claude/skills/ 配下に置けばグローバルに反映されます。1 回作るだけで、何度も節約できます。
2. MCP でローカルツールチェーンを構築して、クラウド呼び出しを代替
Token を消費しがちな処理は、ローカル化できることが多いです。コード検索、ドキュメント問い合わせ、データベース操作など。これらの能力をローカルの MCP ツールとして包み込めば、Claude API への依存が減り、同時にレスポンス速度も上がります。
3. compact ログを監視して、コンテキスト戦略を継続最適化
verbose モードを有効にして、compact がいつ発火し、どれだけ圧縮できているかを観察します。autoCompactThreshold を調整し続け、自分のプロジェクト規模に合うバランスポイントを見つけましょう。
claude --verbose 2>&1 | grep -i compact
4. ソースコードレベルで Permission 分類器を理解する
Claude Code の auto モードの背後には AI 分類器(Transcript Classifier)があります。操作内容からリスクの度合いを判定します。より深く理解したいなら、src/types/permissions.ts にある YoloClassifierResult 型定義を調べてみてください。