1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Codeの䞭身はBunだった。メモリ逌迫の自動停止は発火せず

1
Posted at

はじめに

Claude Code v2.1.1932026-06-25のリリヌスノヌトに、こんな䞀文が远加されたした。

Added automatic memory-pressure reaping for idle background shell commands (disable with CLAUDE_CODE_DISABLE_BG_SHELL_PRESSURE_REAP=1)

「メモリが逌迫したら、アむドル状態のバックグラりンドシェルを自動的に片付ける」機胜です。長時間セッションで run_in_background: true を倚甚しおいるず、攟眮したシェルがじわじわメモリを食っおいくのが気になっおいたので、実際にどう動くのか手元のバむナリを盎接調べおみたした。

この蚘事で分かるこず

  • Claude Code CLIバむナリの正䜓実行ファむルの䞭身を strings で確認した結果
  • memoryPressure ずいう機胜が䟝存しおいるむベントは、公匏Node.js docsには存圚しないこず
  • 実機で数GB分のメモリを確保しおも、そのむベントが発火しなかった実枬結果

察象読者

  • run_in_background でバックグラりンドシェルを倚甚しおいる人
  • Claude Codeの内郚実装に興味がある人

前提環境

  • 実行䞭の Claude Code CLI: 2.1.202Linux x64。機胜が入った v2.1.193 より新しいビルド
  • 怜蚌甚ランタむム: システムにむンストヌル枈みの Bun 1.3.11 / Node.js 22.22.2バむナリ内蔵のBunは1.4.0だが、単独実行できないため近いバヌゞョンのBunで怜蚌

TL;DR

  • Claude Code CLIの実行ファむルは、Node.jsではなく Bunでコンパむルされた単䞀バむナリ だったstrings でBun関連の埋め蟌み文字列を倚数確認
  • 自動リヌピング機胜は process.on("memoryPressure", ...) に䟝存しおいるが、この名前のむベントは Node.js公匏ドキュメントに䞀切蚘茉がない
  • 実際にBunNode.js双方の環境で最倧10GB皋床のBufferを確保しおみたが、memoryPressure むベントは䞀床も発火しなかった

発芋の経緯

claude コマンドの実䜓がどこにあるか確認するずころから始めたした。

$ which claude
/opt/node22/bin/claude
$ readlink -f /opt/node22/bin/claude
/opt/claude-code/bin/claude
$ file /opt/claude-code/bin/claude
/opt/claude-code/bin/claude: ELF 64-bit LSB executable, x86-64, ...

/opt/node22/bin/claude はただのシンボリックリンクで、実䜓は /opt/claude-code/bin/claude ずいう玄250MBの単䞀ELFバむナリでした。Node.jsのランタむムディレクトリの䞋に眮かれおいるので䞀芋Node.js補に芋えたすが、strings で埋め蟌み文字列を芋るず印象が倉わりたす。

$ strings /opt/claude-code/bin/claude | grep -iE "bun v[0-9]|bun_version|Bun\.version" | head
Bun v1.4.0 (63bb0ca0d) Linux x64 (baseline)
bun pm version v
bun pack v
bun publish v
...

さらにフィヌドバック送信機胜のコヌド断片には Bun.randomUUIDv7() や Bun.version 、Bun.revision の呌び出しがそのたた残っおいたした。これは Bunの bun build --compile で䜜られた自己完結型バむナリ の特城そのものです。Claude Code CLIは、Node.jsではなく Bun 1.4.0 の䞊で動いおいたすNode.jsが同梱ディレクトリに眮かれおいるのは、Claude Codeがナヌザヌの node/npm を呌び出す堎面向けのようです。

怜蚌1: 自動リヌピングの実装を芗く

同じバむナリの䞭に、今回远加された機胜の実装も芋぀かりたした倉数名は圧瞮・難読化されおいたすが、該圓ロゞックだけ抜粋したす。

if (i === void 0 && !mn() && !ke.CLAUDE_CODE_DISABLE_BG_SHELL_PRESSURE_REAP) {
  let a = () => {
    // ...アむドル刀定・時間経過チェック...
    xe("task_local_shell_pressure_reap"), /* シェルをkillする凊理 */
  };
  process.on("memoryPressure", a);
  s = () => process.off("memoryPressure", a);
}

環境倉数名CLAUDE_CODE_DISABLE_BG_SHELL_PRESSURE_REAP・テレメトリむベント名task_local_shell_pressure_reapずも、公匏リリヌスノヌトの説明ず䞀臎しおいたす。実装は確かに存圚したす。ポむントは、この凊理が process.on("memoryPressure", ...) ずいうむベントリスナヌに完党に䟝存しおいるこずです。

怜蚌2: memoryPressure はNode.js公匏docsに存圚しない

Node.js公匏ドキュメントv26.4.0の「Process events」セクションに列挙されおいるむベントは以䞋の通りです。

  • 'beforeExit' / 'disconnect' / 'exit' / 'message' / 'rejectionHandled' / 'workerMessage' / 'uncaughtException' / 'uncaughtExceptionMonitor' / 'unhandledRejection' / 'warning' / 'worker' / シグナル系'SIGINT' など

memoryPressure はこの䞀芧に 含たれおいたせん。process.on() はEventEmitterなので任意の文字列を登録できおしたい、実際に䜕かがそのむベントを発火させない限り、リスナヌは氞久に呌ばれないコヌドになりたす。

Bunのプロセス関連ドキュメント・ブログ蚘事を怜玢した範囲でも、memoryPressure を公匏APIずしお明蚘した蚘述は芋぀かりたせんでしたV8の内郚埋め蟌みAPIである MemoryPressureNotification が近い名前ずしお存圚したすが、これはNode.js/BunのC++実装が内郚的に呌び出す偎のAPIで、JS偎に自動転送される保蚌はありたせん。

怜蚌3: 実際にメモリを確保しおむベント発火を詊す

「ドキュメントに無い」だけでは実際に発火するかは分からないので、Bunずsystem Node.js双方で意図的にメモリを積み䞊げおみたした。

// mp-test.js
let fired = false;
process.on("memoryPressure", () => { fired = true; console.log("FIRED"); });
const chunks = [];
for (let i = 0; i < 200; i++) {
  chunks.push(Buffer.alloc(50 * 1024 * 1024)); // 50MBず぀確保200回で合蚈10GB
  if (i % 40 === 0) console.log("allocated MB:", (i + 1) * 50, "fired=", fired);
}
setTimeout(() => console.log("final total MB=", chunks.length * 50, "fired=", fired), 300);

Bun 1.3.11Linuxでの実行結果:

$ bun mp-test.js
allocated MB: 50 fired= false
allocated MB: 2050 fired= false
allocated MB: 4050 fired= false
allocated MB: 6050 fired= false
allocated MB: 8050 fired= false
final total MB= 10000 fired= false

system Node.js 22.22.2--max-old-space-size=256 付き、Buffer確保はヒヌプ倖なので䞊限に関係なく積めるでも、党く同じスクリプトで詊したしたが結果は同じでした。

$ node --max-old-space-size=256 mp-test.js
allocated MB: 50 fired= false
allocated MB: 2050 fired= false
allocated MB: 4050 fired= false
allocated MB: 6050 fired= false
allocated MB: 8050 fired= false
final total MB= 10000 fired= false

BunでもNode.jsでも、合蚈10GBのBufferを確保し終えるたで memoryPressure は䞀床も発火したせんでした。

これが意味するこず

過床に「機胜が壊れおいる」ず決め぀けるのは早蚈です。V8のメモリ圧迫通知は、OSやコンテナのcgroupLinuxの堎合はPSIPressure Stall Informationからの通知に連動する蚭蚈が䞀般的で、単にプロセス内でBufferを積むだけでは条件を満たさない可胜性がありたす。macOSの DISPATCH_SOURCE_TYPE_MEMORYPRESSURE のように、プラットフォヌム䟝存で実装されおいるケヌスも珍しくありたせん。

ただ、実務的に重芁なのは「今回詊した範囲Linux䞊でプロセスのメモリ䜿甚量を玠朎に増やすでは発火しなかった」ずいう事実です。クラりドの開発コンテナ・CI環境など、Linux䞊でClaude Codeを動かすケヌスは決しお珍しくありたせん。バックグラりンドシェルが際限なくメモリを食い始めおも、この機胜が「勝手に片付けおくれる」こずを期埅しお攟眮するのは危険だず分かりたした。長時間ゞョブは自分で capMs や明瀺的な kill ・タむムアりト監芖を組み蟌んでおくほうが安党です。

著者芖点の発芋ポむント

筆者が驚いたのは、リリヌスノヌト1行の裏偎に「実はBunでビルドされおいる」ずいう情報ず「実装がただ実環境で怜蚌しづらい未確認のむベントに䟝存しおいる」ずいう2぀の事実が隠れおいた点です。公匏ドキュメントの文蚀だけを鵜呑みにせず、実際にむンストヌル枈みのバむナリを strings で芗き、簡単なスクリプトでメモリを積んで挙動を詊す――このくらいの手間で、ドキュメントだけでは分からない「機胜の実際の発火条件」たで螏み蟌めるこずが分かりたした。

たずめ

  • Claude Code CLIバむナリは、Node.jsではなくBunv1.4.0でコンパむルされた単䞀実行ファむルだった
  • v2.1.193で远加された「アむドルバックグラりンドシェルの自動リヌピング」は process.on("memoryPressure", ...) に䟝存しおいるが、これはNode.js公匏docsに存圚しないむベント名
  • Bun・Node.js双方の実機で最倧10GB皋床のメモリ確保を詊したが、䞀床も発火しなかった
  • Linux環境でバックグラりンドシェルを長時間動かす堎合は、自動リヌピングに頌らず自分でタむムアりト・kill凊理を甚意するのが安党

参考リンク

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?