プログラミング
OpenCode の使用をやめよう
Stop Using OpenCode (wren.wtf)
要約
この記事は、AIコーディングエージェントであるOpenCodeが、セキュリティ上の深刻な欠陥と非効率な設計により、信頼性に欠けるツールであると批判しています。著者は、プロンプトキャッシュの不具合、コンテキストの不適切な管理、冗長で意見の強いシステムプロンプトといった具体的な問題点を挙げ、ユーザーにOpenCodeの使用停止を強く推奨しています。
全文翻訳
もしあなたがOpenCodeが何であるか知らないなら、それは永遠に人間の顔を踏みつけるブーツだと想像してください。そのブーツはTypeScriptでできており、顔は1940年代に電子コンピューターが発明されて以来、私たちがセキュリティとシステムソフトウェアについて学んできたすべてです。開発者はそれをAIコーディングエージェントと説明しています。私の知る限り、これは最も人気のあるオープンソースのコーディングエージェントであり、現在GitHubで161kのスターを獲得しています。
私はローカルLLMでOpenCodeを試してみました。私の結論は、OpenCodeはセキュリティ体制が「喜んであなたのために身をかがめますよ、ダーリン」というような、ピエロの車のようなひどい代物だということです。それを使っているすべての人々は、使用をやめるべきです。
この投稿には2つの部分があります:面倒な点と、懸念される点です。後者の方が長いです。私はOpenCodeのgitバージョンbaef5cd4のソースコードを参照してこの投稿を書きました。この投稿のいかなる内容もセキュリティ開示とは考えていません。
OpenCodeは基本的に、llm | bash をパイプするウェブスタックツールであり、私が説明するすべての問題は「パイプ」の部分にあります。その失敗の仕方は、貧弱な意思決定のフラクタルな性質において魅力的ですが、結果は予測されていました。私はLLMの使用に関する議論を、誰もがLLMを使用しているマシンが簡単に悪用されるか、誤って消去されるべきかどうかという問題から切り離しておこうとしました。ローカルLLMに関する簡単な考察を添えた追記があります。
面倒な点
ひとまずセキュリティは脇に置いて、OpenCodeがあなたのものを台無しにしていない場合でも、ツールとしてどのように失敗するかを調べてみましょう。OpenCodeには、それがバグなのか意図的なものなのか区別がつかないBethesda効果のようなものがあり、私は「面倒」という説明に留めました。
プロンプトキャッシュのミス
ほとんどのローカルLLMサーバーは、OpenAIの/v1/chat/completions APIのバリアントを使用しています。その考え方はこうです:JSONブロブ全体にこれまでの会話全体を含めてPOSTします。SSEイベントのストリームを受け取り、それが応答を構成します。セッション中のアップロードコストは二次関数的であり、ダウンロードは小さな差分をJSONでラップし、メタデータを繰り返すことで増幅されます。ツール呼び出しは、複数のJSONエンコードされた差分としてシリアル化できるように、捉えどころのない「ダブルJSONエンコーディング」を使用しており、それらはさらにJSONを再構築します。
このセットアップの1つの利点は、サーバーがステートレスであることです。いつものように、ステートレスなものを速くする方法は、ステートです。サーバーは評価をキャッシュします。リクエストを受け取ると、それは:
最も長い一致するキャッシュされたプレフィックスを見つけます。
プレフィックスの末尾から、最後に投稿されたメッセージの末尾までを評価します(「プリフィル」)。
シーケンス終了トークンに遭遇するまで新しいトークンを生成します。
私はM4 MaxでQwen3.6-27B denseを使用しました。これはまともなメモリ帯域幅(約0.5 TB/s、SoC CPUとしては高いがGPUとしては低い)を持っています。トークン生成は実用的ですが、プリフィルでは非常に計算量が多くなります。もし私のサーバーが、ウィンドウの奥深くでリクエストプロンプトに一致する良いプレフィックスを見つけられない場合、応答の生成を開始するために最大GPU使用率で10分待たなければならないかもしれません。それは問題ありません、なぜならこれはまれにしか起こらないはずだからです。はずです。
OpenCodeがこの点に関してメモを逃した方法はいくつかあります:
それはファイルシステム全体をグロブし、すべてのSSEターンでAGENTS.md(ターン0のシステムプロンプトに注入される)を再読み込みします。次のセッションで読み取られるAGENTS.mdに簡単なメモを入れると、すぐに完全な再評価を強制します。
それは各エージェント→ユーザー遷移でツール呼び出しからコンテキストをプルーニング(枝刈り)し、プレフィックスの大部分を無効にします。プルーニングは、書き込みヘッドから固定距離40,000より後ろのツール呼び出し結果を単に破棄します。最良の場合、40kコンテキストのミスが発生し、これは2〜3ターンごとにフルレングスの小説を読むことに相当します。エージェント→ユーザー遷移には割り込みが含まれるため、クランカーをウサギの穴から引き出して再誘導する必要がある場合、OpenCodeは即座にプロンプトキャッシュを台無しにし、応答を待たせることになります。
私のお気に入りは、現在の日付をターン0のシステムプロンプトに入れ、すべてのSSEターンで再評価することです。あなたが深夜にOpenCodeを使用している場合、あなたは完全なプロンプトキャッシュミスを経験します。これは、クランカーが現在の С をトレーニングカットオフの日付だと信じ込み、新しいものが存在することを信じなくなる傾向を是正しようとしているのだと思います。それはまだ面白いです。
これらは、このカテゴリだけに該当するプロンプトキャッシュのミスです。他にもたくさんありますが、進むにつれてそれらを指摘します。
プルーニング
前のセクションでプルーニングについて言及しました。プロンプトキャッシュのミスはそれに見合う価値がないので、私はそれを無効にしました。
もう一つの明白な問題は、早期読み込みに対する保護の欠如です。これがどれほど完全に壊れているかは明らかではないかもしれませんので、例を挙げてみましょう。新しいセッションを開始し、クランカーにまず仕様書または実装計画を読み込ませ、その後コードを書くように指示したとします。
仕様書はコンテキストに読み込まれます。クランカーは関連するコードを読みに行き、それは非常に高い確率で固定された40kプルーニング閾値を超えます。クランカーは実装の準備ができていますが、すぐにばかげた穴に飛び込むか、実際には非常に単純なことやすでに明確に定義されていることについて、チェーンオブソートでぐずぐずしています。あなたはクランカーを中断して再誘導します。その割り込みにより、仕様書全体がコンテキストウィンドウから削除されます。クランカーは仕様書を参照できずにコードを書きます。
プルーニングは、スキルを除くすべてのツールのすべての結果に同様に適用されます。スキルは決してプルーニングされません。
コンパクション
セッション全体を新しいプロンプトを先頭に付けてLLMサーバーにプリフィルさせるために10分間待って、それを新しいセッションの先頭に行く5つの箇条書きにするのはどうですか?私もそうしたくありません。彼らが何をしようとしているかは理解できますが、それがうまく機能するのを見たことがありません。コンパクションもプルーニングも適切に実装されておらず、相互に悪影響を及ぼします。
セッションを要約したい場合、要約プロンプトはセッション全体をゼロからプリフィルすることを避けるために末尾に注入されるべきです。私が発見した最良の方法は、クランカーにメモを書き出すように指示する明示的な引き継ぎです。それは醜いですが、OpenCodeのコンパクションメカニズムよりもうまく機能し、私が編集したり複数のセッションで再利用したりできるディスク上の成果物を作成します。
コンパクションは、有限のコンテキストウィンドウを無限のもののように見せかけようとする、漏洩した抽象化です。コンテキストウィンドウとプロンプトキャッシュをクランカーの操作のファーストクラスの機能として受け入れ、それらを管理するためのより良いプリミティブを公開する方が良いです。Piは、プロンプトキャッシュを意図的に利用するセッションツリーという興味深いアプローチを持っています。
システムプロンプト
OpenCodeは新しいコンテキストウィンドウの先頭にシステムプロンプトを貼り付けます。それは問題なく正常ですが:
デフォルトのシステムプロンプトは信じられないほど冗長です。皮肉なことに、単語数のほとんどはLLMに簡潔になる方法を説明するために費やされています。
デフォルトのシステムプロンプトは意見が強い(それは良い)ですが、その意見はひどい(それは良くない)です。私のエージェントがサブエージェントをディスパッチする際に「絶対にコメントを使用しないでください」と常に言っていた理由を理解するのにしばらく時間がかかりました。
プラン・トゥ・ビルドの引き継ぎはぎこちなく、すべてが十分に解明された頃にはコンテキストウィンドウの終盤にいることがよくあります。私はメモを書き出して編集し、その後新しいセッションに引き継ぐ方が良いです。
それに、次の点をご覧ください:
プランモードのシステムリマインダーは、クランカーがいかなるディレクトリにも書き込めないことを伝えますが、実際には特定の.opencode/plansディレクトリには書き込むことができます。私はこれが両方の方法で失敗するのを見ました:このディレクトリに無断で書き込むこと、そして明示的に指示されたときに書き込みを拒否すること。
デフォルトのシステムプロンプトをグローバルに変更する方法はありません。すべてのプロジェクトにコピーする必要があります。デフォルトのプロンプトをビルドモードでのみオーバーライドすると、プランモードに切り替える際に完全なプロンプトキャッシュミスが発生します。
モデルごとのプロンプトは、内容と品質が大きく異なります。それらはすべて、じっくりと憎しみを込めてスクロールする価値がありますが、Beast Mode(GPT-4、o1、o3)が私のお気に入りです。
引用:「サードパーティパッケージと依存関係に関する理解が最新であることを確認するために、Googleを使用せずにこのタスクを正常に完了することはできません。できません。私たちは方法を知りません。絶対にパッケージのソースコードを読むだけはやめてください。」
パーミッションプロンプト W