1. 生成済みのファイルを出力し直している?
Claude.aiで文書ファイルを生成していたら、Markdownファイルを作ったあと、改めてその直後に cat > file.md << 'ENDOFFILE' というコマンドで、同じ内容をまるごと再出力していました。

すでにファイルは生成されているものの、もう一度ヒアドキュメントのコマンドを出力するのは無駄に見えます。
1.1. claude.aiは会話ごとにコンテナを起動する
claude.aiでファイル作成機能を使うとき、内部では専用のUbuntuコンテナが動いています1。

「コンテナ」とは、アプリケーションとその実行に必要なファイル・設定をひとまとめにして、ホストOSから隔離して動かす仕組みです。
Dockerが普及させた技術で、同じマシン上に複数の独立した環境を軽量に立ち上げられます。
ユーザーのシステムに直接触れない安全な実行環境として使われています。
Ubuntuコンテナは、会話ごとに新規に起動する使い捨ての環境で、”wiggle” のようなコンテナ名が付けられています2。
このコンテナ内のファイルシステムには、役割ごとに決まった保存場所があります3。
/home/claude/:Claudeの作業ディレクトリ。コンテナが終了すると消える/mnt/user-data/outputs/:ユーザーに渡すファイルを置く場所。セッションをまたいで永続する/mnt/user-data/uploads/:ユーザーがアップロードしたファイルの置き場/mnt/skills/:Word・PDF・PowerPointなど形式別の作成手順書(SKILL.md)が入っている
Claudeがチャット画面に表示されたテキストは「画面に表示されたトークンのストリーム」で、コンテナ内のファイルシステムは直接つながっていません。
ファイルとして保存するには、明示的な書き込み操作が必要です。
Claudeがファイルを作るときは、まず /home/claude/ に作業ファイルを置き、完成後に present_files というツールで /mnt/user-data/outputs/ にコピーする、という段取りになります。
この設計の必然として、同一ファイルが2カ所に存在することになります4。
2. create_file があるのに cat が使われる(ヒアドキュメント)
Claudeには create_file というツールがあります。
このツールを使えば、ファイルの内容をパラメータとして一度渡すだけで書き込みが完了します。
にもかかわらず、実行コマンドで同じ文章を書き込んでいることがあります。
cat <<EOF ... EOF のような記法を「ヒアドキュメント」と呼びます。
シェルスクリプトで複数行のテキストをそのままコマンドに渡す構文で、この場合 EOF(End Of File)で囲まれた範囲がそのまま標準入力として扱われ、catコマンドでファイルに書き込みます。
ファイルへの書き込みだけでなく、コマンドへのテキスト渡しにも広く使われる、Unix系システムの慣用的な書き方です。
しかし、この方法では、生成済みのテキストを再びコードとして生成するためトークンを浪費してしまいます。
Anthropicの公式GitHubにも、この問題を指摘したissueが存在します5。
そこでの議論には「Claudeが cat heredoc の方が効率的だと信じているのは、誤った効率性ヒューリスティックだ」という考察があります。
2.1. 学習したスクリプトにヒアドキュメントが多い?
言語モデルが間違った前提を持っているということですが、その前提がどこから学習したのでしょう。
おそらくシェルスクリプトや開発者向けのドキュメントだと考えられます。
これらのドキュメントでは、ファイルを作る慣用句として cat <<EOF が広く使われます。
学習データにそのパターンが大量に含まれていれば、モデルはそれを「ファイルを書くときの自然な方法」として学びます。
Claudeがコマンドを組み立てる時には、create_file のような専用ツールより、馴染みの深いシェルスクリプトの方が先に浮かんでしまうわけです。
実は、システムプロンプトには「ファイル書き込みにはcatやechoでなくWriteツールを使え」と明示されているのですが6、指示があっても言語モデルが常に従うとは限りません。
事前学習で身についた傾向とシステムプロンプトの指示が競合したときには、学習内容の方が勝つことも少なくなく、「構造的な問題」になっています。
2.2. LLMベースのシステムの問題
この挙動には3つの層が絡んでいます。
- モデルが誤ったヒューリスティックを持っている。
- システムプロンプトでの矯正が完全には機能しない。
- ファイル出力の2ステップ構造が問題を増幅する。
claude.aiの作業ディレクトリとoutputsが分離している設計上、同一ファイルのコピーが起きやすく、そのときに「Writeツールを使え」と指示しても、学習データの偏りから cat <<EOF の方が効率的だと思い込んでしまい従わないのです。
つまり、「なぜこんな非効率なことをするのか」という疑問への答えは、「単純な手抜き」ではありません。
モデルの事前学習、ツール設計、システムプロンプトによる行動誘導、この3つが噛み合っていないときに起きる、LLMベースのシステム特有の問題です。
こういう「なんとなく非効率な挙動」の背景を理解しておくと、ツールの限界を正しく見積もれますし、何かがおかしいと気づいたときに原因を特定しやすくなります。
3. 【補足】Claude Codeのヒアドキュメント問題
Claude Codeでも似たような問題が報告されています7。
書き込みコマンドの承認判定が、繰り返し必要になる問題です。
Claude Codeには人間がコマンド実行を承認するパーミッションシステムがあります。
組み込みツール(WriteやEditなど)の操作は一度承認したら記録できます。
しかし、ヒアドキュメントを使うとコマンド内容が毎回変わるため、改めて承認が必要です。cat <<EOF を使うたびに人間の目視確認が発生するのです。
一方、Writeツールなら差分表示で確認が済みます。
せっかく、生成AI用に用意された専用ツールが、活用されないのはもったいないです。
- 2025年9月、Anthropicがclaude.aiにファイル作成機能を追加した際、開発者のSimon Willisonがコンテナをリバースエンジニアリングし、Ubuntu 24.04 LTS、RAM約9GB、Python 3.12.3、Node.js 18.19.1という構成を確認しました。 – Claude Code Interpreter review – simonwillison.net
- dev.toのエンジニアがclaude.aiの内部ファイルシステムを実際に探索し、コンテナ名・ディレクトリ構成・ツール名を記録しています。 – Inside Claude’s Sandbox: What Happens When Claude.ai Creates a File – DEV Community
- Anthropicの公式サポート記事では、claude.aiのファイル作成がコンピューティング環境(プライベートなコンテナ)で実行され、ユーザーのシステムとは分離されていると説明しています。 – Create and edit files with Claude – Claude Help Center
- present_filesを使うと
/home/claude/と/mnt/user-data/outputs/の両方にファイルが存在し、後続の編集でどちらを更新したかによって「変更が反映されない」という混乱が起きやすいことが、ユーザーによる実験で確認されています。 – Inside Claude’s Sandbox: What Happens When Claude.ai Creates a File – DEV Community - Claude CodeのGitHubリポジトリに登録されたissue #19649では、
cat heredocによるファイル作成が「最も重大なパターン」として分析されており、「Claudeが cat heredoc の方が効率的だと信じているのは、誤った効率性ヒューリスティックである」と明記されています。 – Frequently uses Bash tools when use-case is well aligned to other builtin tools · Issue #19649 · anthropics/claude-code - Claude Codeのシステムプロンプトを全バージョン追跡しているPiebald-AIのリポジトリに、「ファイル書き込みにはecho/catでなくWriteを使え」「ファイル読み込みにはcat/head/tailでなくReadを使え」というツール説明が含まれることが記録されています。 – claude-code-system-prompts – Piebald-AI
- issue #19649には「パーミッションシステムは組み込みツール操作の承認をキャッシュできるが、heredocのように内容が毎回異なるBashコマンドはキャッシュできないため、全文レビューが毎回発生する。これがheredocを使う際の追加コストである」と詳述されています。 – Frequently uses Bash tools when use-case is well aligned to other builtin tools · Issue #19649 · anthropics/claude-code