Emacs から AI を使う構成は、一つの製品や一つの操作方法には収まらない。通常のバッファからモデルへ要求を送る方法、Claude Code の対話画面を Emacs 内のターミナルへ表示する方法、外部で動く対話画面へ Emacs の通常バッファから文字列を送る方法がある。画面上ではいずれも Emacs から指示を入力して回答を読むが、AI を呼び出す主体、入力を処理する層、会話履歴の保存場所、Emacs を閉じた後も処理が続く条件は一致しない。
この違いは、障害時と再開時に表面化する。モデルから返答が来ないとき、Emacs が直接 API を呼ぶ構成では、認証、通信、接続先 API、Emacs 側の要求処理を順に確認する。Claude Code をターミナルバッファで動かす構成では、これらに Claude Code CLI とターミナル実装が加わる。Zellij を介する構成では、さらに外部セッション、対象ペイン、画面取得、会話記録の対応を確認しなければならない。同じ「応答が表示されない」という現象でも、接続方式によって原因候補と復旧手順が変わる。
Emacs 統合が直接変えるのは、モデルの推論能力ではなく、指示、文脈、回答を受け渡す経路である。選択範囲やファイルを別の画面へコピーする操作が減り、返答を通常のバッファへ置くことで、検索、保存、Undo、差分比較など、既存の編集機能を生成結果の確認へ使えるようになる。一方、外部 CLI、ターミナル、セッション管理機能を追加するほど、Emacs が表示する状態と、実際に処理を続けている外部プロセスの状態は分かれる。利便性は操作経路の短縮から生じ、保守負担は状態の分散から生じる。
1. Emacs と AI の接続は三つの実行配置に分かれる
1.1 gptel は通常のバッファからモデルを呼び出す
Emacs のバッファは、画面に表示された文字列だけを保持する領域ではない。ファイルとの対応、保存後に加えられた変更、使用中のファイル種別ごとの編集機能を決めるメジャーモード、バッファ固有の変数などを持つ編集単位である[1]。同じ文字列を表示していても、ファイルを開いたバッファ、会話を保存したバッファ、一時的な結果を表示するバッファでは、保存、再読込、編集支援の動作が異なる。
gptel は、このバッファをモデルとの入出力に使う。専用の会話バッファを作るほか、文章やソースコードを開いている通常のバッファから問い合わせ、選択範囲を書き換え、別のバッファやファイルを追加の文脈として指定できる[2]。質問文だけを別の画面へ貼り付けるのではなく、現在の選択範囲、編集対象、追加した資料を Emacs 側で対応付けたまま要求を作れる。
処理経路は、Emacs が要求を組み立て、クラウド API またはローカル API へ送り、返答を文字列としてバッファへ挿入する形になる。Claude Code のような対話型プログラムの画面を再現しないため、端末のカーソル制御、罫線表示、対話メニューを解釈する層は必要ない。返答が通常のテキストとして入ることで、検索、コピー、Undo、ファイル保存、別バッファとの比較を通常の編集操作として実行できる。
この構成では、会話と編集対象を同じバッファ機構で扱える一方、バッファに見えている内容とモデルへ実際に送られる内容が常に同一とは限らない。追加済みのファイル、システム指示、過去の会話、選択中のモデルなどは、画面上の本文とは別の設定として要求へ加わる場合がある。通常バッファとの一体性を生かすには、表示された回答だけでなく、どの範囲と追加文脈が要求に含まれているかも確認対象になる。
1.2 claude-code.el は Claude Code の対話画面を Emacs 内へ入れる
claude-code.el は、Emacs 側に独自の会話処理を作るのではなく、Claude Code CLI を起動し、その対話画面を Emacs のターミナルバッファへ表示する。現在のファイルと行番号、選択範囲、ファイル自体を Claude Code へ送る機能も備える[3]。Emacs は起動、表示、対象範囲の受け渡しを担うが、会話の進行、ファイルの読み取り、編集、コマンド実行は Claude Code のプロセスが担う。
Claude Code は、回答文だけを返すチャットではなく、進行状況、実行した処理、許可確認、選択肢、対話コマンドを文字端末上へ表示する[4]。claude-code.el がターミナル画面を内包することで、これらの表示と操作体系を大きく変えずに Emacs 内へ持ち込める。Claude Code が処理の途中で確認を求めた場合も、専用の対話状態を保ったまま応答できる。
この忠実性と、通常バッファの編集性は別の入力経路から生じる。ターミナルバッファでは、キー入力の多くが Claude Code を動かす子プロセスへ渡されるため、Emacs の通常コマンドと Claude Code の対話操作が同じキーを利用すると、どちらが入力を受け取るかを切り替える必要が生じる。Emacs 内部で文字を組み立てる入力メソッドや、通常バッファを前提とする編集機能も、対話欄へ直接介在できない場合がある。
ターミナル実装が保持する画面と、Emacs の通常バッファが保持する文章は、同じ文字を表示していても内部構造が異なる。対話画面の表示を優先する構成では、Claude Code 固有の操作を保ちやすい代わりに、回答全体を通常の文章として検索、再編集、保存するには、読み取り専用表示への切り替えや別バッファへの転記が必要になる。claude-code.el の適性は、Emacs の編集操作を最大限に使うことより、Claude Code の対話画面を Emacs から離れずに操作することを重視する場合に高くなる。
1.3 zellij-send.el は外部セッションの入出力を仲介する
zellij-send.el は、Claude Code などの対話型エージェントを Zellij の切り離されたセッションで動かし、Emacs の通常バッファから Zellij 内の分割画面である対象ペインへ文字列を送る。Emacs 内にターミナルを表示し続けるのではなく、通常の Emacs バッファと、外部で動く対話画面を結び付ける構成である[5]。
指示は通常の Emacs バッファで作成するため、送信前には検索、置換、Undo、キルリング、Emacs 内部の入力メソッドを利用できる。文字列の作成が完了した後で Zellij のペインへ送るため、Claude Code の対話画面がキー入力を直接受け取る構成とは異なり、長い日本語の指示を通常の文章と同じ手順で推敲できる。Emacs で完成させた文字列だけを外部の対話画面へ渡すことにより、ターミナル内で Emacs の入力メソッドが動作しない制約を回避する。
返答には二つの取得経路がある。現在の進行状況を確認するときは、Zellij のペインに表示されている画面を Emacs へ転写する。会話の冒頭から読み直すときは、Claude Code が保存した会話記録から全体を再構成する。対話型プログラムが使用する画面には、現在表示中の範囲しか残らない場合があるため、画面取得だけでは、上方へ流れた長い回答やツール実行結果を復元できない。ライブ表示と永続的な履歴を分ける構成は、この表示上の制約から生じている。
Zellij のセッションは Emacs のウィンドウから切り離されているため、別のバッファを編集している間も処理を続けられる。Emacs を再起動した後に、残っている Zellij セッションへ再接続する構成も成立する。その代わり、現在の入力文は Emacs バッファ、実行状態は Zellij のペイン、会話履歴は Claude Code の記録、作業結果は外部ファイルというように、状態が複数の場所へ分かれる。同じ作業ディレクトリで複数のセッションを動かした場合には、どのペインとどの会話記録を対応付けるかが新たな管理条件になる。
| 方式 | 処理を実行する主体 | 指示の入力経路 | 回答と履歴の所在 | 処理が継続する条件 | 固有の利点 | 不整合が起きる条件 |
|---|---|---|---|---|---|---|
| gptel | Emacs が接続先 API へ要求を送り、返答を受け取る。 | 通常バッファ、選択範囲、追加したバッファやファイルから要求を作る。 | 回答は通常バッファへ入り、会話は保存した文書やバッファ状態として保持される。 | Emacs が動作し、要求先の API へ接続できる間に処理する。 | 回答を通常の文章として検索、編集、保存、比較しやすい。 | 画面上の本文と、追加文脈や設定を含む実際の送信内容を取り違える場合がある。 |
| claude-code.el | Claude Code CLI が会話、ファイル操作、コマンド実行を担う。 | Emacs 内のターミナルへ直接入力するか、通常バッファの範囲やファイルを送る。 | 回答と進行状況はターミナル画面へ表示され、会話状態は Claude Code 側で管理される。 | Claude Code のプロセスと、それを収容する Emacs のターミナルが動作している間に継続する。 | 許可確認、進行表示、対話コマンドを含む Claude Code の画面を保ちやすい。 | ターミナルのキー処理と Emacs の編集操作や入力メソッドが競合する場合がある。 |
| zellij-send.el | Zellij のペイン内で動く Claude Code などが処理を担う。 | 通常の Emacs バッファで指示を完成させた後、対象ペインへ文字列を送る。 | 現在画面は Zellij から取得し、長い会話は Claude Code の記録から再構成する。 | Zellij のセッションが残っていれば、Emacs の表示状態とは独立して処理を継続できる。 | 通常バッファの編集性と、外部セッションの継続性を組み合わせられる。 | Emacs バッファ、対象ペイン、会話記録、作業ディレクトリの対応がずれる場合がある。 |
三方式は、同じ機能を異なる画面で提供しているのではない。gptel は、モデルへの要求と回答を Emacs のバッファ機構へ寄せる。claude-code.el は、Claude Code の対話状態を保ったままターミナル画面を Emacs 内へ置く。zellij-send.el は、入力と閲覧を通常バッファへ移しながら、実行プロセスを外部セッションへ残す。どの方式を選ぶかによって、Emacs が直接管理する範囲と、外部プロセスへ委ねる範囲が変わる。
選択の基準になるのは、Emacs へ何を取り込みたいかである。回答を通常の文章として扱うことを優先するなら gptel が適合する。Claude Code の許可確認や対話画面を保つ必要があるなら claude-code.el が適合する。Emacs の入力機能を使いながら、複数の処理をバックグラウンドで継続させるなら zellij-send.el が候補になる。操作経路を短くする対象を増やすほど、状態の対応付けと障害切り分けに必要な構成要素も増える。この配置差が、後続の利点と欠点を決める。
2. バッファを接点にすると指示と編集対象の距離が縮まる
2.1 リージョン、バッファ、ファイルを文脈として指定できる
ブラウザー型の対話では、編集対象から必要な部分をコピーし、質問欄へ貼り付け、返答を元の編集環境へ戻す。この往復では、文字列そのものは渡せても、その文字列がどのファイルのどの位置にあり、周辺でどのような変更が進んでいるかまでは自動的に引き継がれない。複数の断片を貼り付けた場合には、引用元の対応関係も質問文の中で説明し直す必要がある。
Emacs 統合では、編集中の対象をリージョン、バッファ、ファイルという単位で指定できる。gptel はバッファやファイルを追加の文脈として登録し、選択範囲を原文とする書き換え要求を作成できる。送信直前には、モデルへ渡される要求内容を検査する機能も備える[6]。コピー先を作る操作が減り、編集対象と要求内容の対応を Emacs 側に残せるため、返答を受け取った後も、どの箇所に対する回答であったかを追いやすい。
ただし、バッファを指定すれば必要な文脈が自動的に確定するわけではない。関数の本体だけを選択すれば、呼び出し側が要求する前提や関連する型定義が欠ける。反対に、ファイル全体や複数のバッファを無条件に追加すると、回答に不要な内容まで入力へ入り、どの情報が判断へ影響したかを追いにくくなる。文脈指定の精度は、送信単位を細かくできることではなく、その単位が質問に必要な前提と一致しているかで決まる。
| 指定単位 | 保持しやすい対応関係 | 不足した場合 | 過剰な場合 |
|---|---|---|---|
| 選択範囲 | 質問対象と原文の範囲を明示できる。 | 定義元、呼び出し側、前後の条件が欠け、断片だけで判断させる。 | 複数の論点を一度に含め、どの部分への回答か曖昧になる。 |
| 現在のバッファ | 編集中の文書と質問を直接対応付けられる。 | 別ファイルにある前提や関連資料が入力へ入らない。 | 質問に無関係な章、設定値、機密情報まで含める可能性がある。 |
| ファイル | 名称と内容を一つの資料として渡せる。 | 関連ファイルが欠けると、単独では成立しない内容を誤って完結したものとして扱わせる。 | ディスク上の保存済み内容と未保存バッファの内容を取り違える場合がある。 |
| 複数ファイル | 相互に参照する資料を一つの要求へまとめられる。 | 必要な依存関係の一部だけが欠け、整合しているように見える不完全な回答を生む。 | 入力が増え、回答がどの資料に基づくかを追跡しにくくなる。 |
| 会話履歴 | 前の質問、回答、修正条件を継続できる。 | 過去の定義を失い、同じ前提を繰り返し説明する必要が生じる。 | 既に撤回された条件や古い判断が、後続の回答へ残り続ける。 |
ファイルとバッファの区別も、文脈指定では実務的な差になる。Emacs 上で未保存の変更を含むバッファを見ていても、外部の仕組みがファイルを読み直す場合には、保存前の内容は渡らない。反対に、バッファ本文を直接送る方式では、ディスク上の状態より新しい内容が入力へ入る。画面に表示されている文章、保存済みファイル、AI へ送られる文字列が同一であるかは、接続方式と送信操作ごとに確認する必要がある。
2.2 通常バッファなら Emacs の入力と編集を維持できる
Emacs の入力メソッドは、押されたキーをそのまま外部プログラムへ渡すのではなく、Emacs 内部で文字列へ変換してからバッファへ挿入する。ddSKK、組み込みの Quail、TeX 入力による記号変換は、この経路を利用する[7]。通常バッファで指示を書く場合には、入力メソッドに加えて検索、置換、キルリング、略語展開、Undo を使える。長い指示を一度で完成させる必要はなく、通常の文章と同じように修正した後で送信できる。
ターミナルバッファでは入力経路が異なる。vterm や eat は、Claude Code などの対話型プログラムを動かすために、Emacs が文字として確定する前のキー操作を子プロセスへ渡し、子プロセスがその入力を対話画面の操作として解釈する。このため、OS 側で確定した日本語入力は使用できても、Emacs Lisp として動作する入力メソッドや、通常バッファを前提とした編集コマンドは、そのままでは介在できない場合がある。
zellij-send.el は、入力と実行を二つの段階へ分ける。最初に通常バッファで指示文を完成させ、その後、完成済みの文字列を Zellij 内の対話画面へ送る。Claude Code が個々のキー入力を受け取るのではなく、Emacs が確定した文字列を一括して受け取るため、対話画面の操作体系を変更せずに Emacs 側の入力機能を利用できる。
| 入力場所 | キー入力を最初に処理する主体 | 利用しやすい機能 | 主な制約 |
|---|---|---|---|
| 通常バッファ | Emacs がキー入力を文字列へ変換する。 | 入力メソッド、検索、置換、Undo、キルリング、補完を利用しやすい。 | 外部の対話画面へ送る操作と、返答を再取得する仕組みが別に必要になる。 |
| ターミナルバッファ | ターミナル実装を経由して子プロセスが入力を受け取る。 | Claude Code 固有の対話操作、許可確認、進行表示をそのまま扱いやすい。 | Emacs 内部の入力メソッドや通常の編集コマンドが介在しにくい。 |
通常バッファを使う利点は、日本語が入力できることだけではない。送信前の文章を、AI へ渡す命令ではなく編集対象として扱える点にある。条件の重複を削り、対象範囲を明示し、誤解される表現を修正してから送信できる。入力の完成度が上がれば必ず正しい回答になるわけではないが、少なくとも指示文の曖昧さと入力操作上の制約を分けて考えられる。
2.3 ローカル LLM も同じ編集経路へ置ける
gptel の接続先はクラウド API に限定されない。Ollama は通常、同じ端末の localhost にある 11434 番ポートでモデル操作用 API を提供する[8]。gptel の接続先を Ollama に設定すれば、通常バッファからの質問、選択範囲の書き換え、追加文脈の指定といった操作を変えずに、生成処理だけをローカルモデルへ切り替えられる。
操作方法が共通でも、クラウドモデルとローカルモデルの実行条件は異なる。Emacs は同じ形式の要求を異なる接続先へ送れるが、返答時間と扱える入力量は、接続先のモデル、文脈長、推論速度、端末のメモリー容量によって変わる。Emacs 側の画面が共通でも、処理能力まで共通化されるわけではない。
既稿で整理したローカル LLM の価値は、最大規模のモデルを端末内で再現することではなく、入力、保存、検索、外部接続の境界を利用者側で構成できる点にある[9]。Emacs は、どのリージョンやファイルを入力へ含めるかを選ぶ操作面になる。Ollama は、要求を受け取りモデルを実行する層になる。モデルファイルは Ollama が管理し、会話の表示と保存は gptel と Emacs が担う。すべてが同じ端末内にあっても、役割と状態は一つに統合されない。
| 層 | 担う処理 | 確認できる現象 | 失敗時に疑う対象 |
|---|---|---|---|
| Emacs と gptel | 対象範囲を選び、要求を作成し、回答をバッファへ表示する。 | 送信操作、接続エラー、回答の挿入状態を確認できる。 | 接続先設定、モデル名、要求内容、Emacs 側の通信処理を確認する。 |
| Ollama API | 要求を受け付け、指定されたモデルの実行を開始する。 | API の応答、利用可能なモデル一覧、エラー内容を確認できる。 | Ollama の起動状態、待ち受け先、API の到達性を確認する。 |
| ローカルモデル | 入力から生成結果を計算する。 | 読み込み時間、生成速度、メモリー使用量、回答内容に現れる。 | モデルの形式、端末資源、文脈長、モデル自体の能力を確認する。 |
| 会話バッファと保存文書 | 質問、回答、追加指示を表示し、必要に応じて保存する。 | 現在の会話内容、過去の前提、未保存の変更を確認できる。 | 古い会話履歴、保存漏れ、別セッションとの取り違えを確認する。 |
ローカル RAG の構築では、画面、生成 API、埋め込み処理、検索索引を一つの機能として確認するのではなく、隣接する層を一方向ずつ接続して障害箇所を切り分けた[10]。Emacs と Ollama の接続でも、同じ分離が必要になる。Emacs から要求自体が送られない状態、Ollama API が応答しない状態、モデルを読み込めない状態、モデルは動くが回答が要求を満たさない状態では、修正対象が異なる。
たとえば、Ollama の API へ直接要求すると回答が返るのに、Emacs からは失敗する場合、モデルの能力や端末資源を調べても原因には届かない。Emacs と gptel の設定、モデル名、接続先を確認すべきである。API へ接続できてもモデルの読み込みで停止するなら、確認対象は Ollama と端末資源へ移る。回答は返るが内容が不十分な場合には、通信経路ではなく、入力範囲、プロンプト、モデルの能力を評価する。この順序を分けることで、「ローカル LLM が動かない」という一つの症状を、設定、通信、実行、品質の問題へ分解できる。
バッファを接点にすることで短くなるのは、モデルが回答を生成する時間ではなく、編集対象を指定し、要求を作り、結果を元の文書へ戻すまでの操作経路である。リージョン、ファイル、会話履歴を直接扱えるほど、コピーによる由来の消失は減る。一方、画面に見えているバッファ、実際に送信される文脈、接続先の API、モデルが保持する状態は別に存在する。操作の一体性を利用するには、内部の境界まで一体化したと誤認しないことが条件になる。
3. Emacs の編集機能は生成と採用の間に検査点を置ける
3.1 生成結果を差分として受け取れる
文章やコードの書き換えを別画面の対話サービスへ依頼すると、返答は完成した文章やコードとして戻る。元の内容と生成結果を比較するには、変更前の版を残し、返答を別ファイルへ貼り付け、差分表示へ渡す工程が必要になる。この工程を省いて生成結果で原文を直接置き換えると、削除された条件、意味が変わった表現、追加された前提を、完成後の文章から人間が探し直さなければならない。
gptel の書き換え機能は、選択範囲を原文として保持し、AI が提案した追加、削除、置換を元の範囲との差として表示する。人間はその差分を読んだ後に、採用、破棄、追加修正を選ぶ。生成と反映を別の操作にすることで、モデルの出力がバッファへ現れた時点と、文書の正式な内容として採用された時点を区別できる。
Emacs の Undo は、バッファへ加えられた変更を履歴から戻す機能である[11]。Ediff は、二つまたは三つのファイルやバッファを並べ、対応する差異を移動しながら比較できる[12]。これらは AI 専用に作られた機能ではないが、生成結果が通常のバッファ変更として扱われることで、従来の編集履歴と比較機能をそのまま検査へ使える。
差分表示が有効なのは、変更量を数えられるからではない。変更前に存在した条件が残っているかを確認できる点にある。たとえば、文章を簡潔にする指示に対して、重複表現だけでなく留保条件まで削除される場合がある。コードの整理では、重複処理の削減とともに例外処理や互換性条件が消える場合がある。完成後の文章やコードだけを見ると自然に読めるため、消失した条件には気付きにくい。元の版と対比すれば、読みやすさの改善と引き換えに何が失われたかを行単位で確認できる。
| 変更の種類 | 差分で確認する対象 | 完成結果だけでは見落としやすいこと |
|---|---|---|
| 削除 | 条件、例外、留保、定義、前提が残っているかを確認する。 | 文章が滑らかになったことで、必要な制約まで消えたことに気付きにくい。 |
| 追加 | 原文にない事実、評価、因果、例示が挿入されていないかを確認する。 | 文体が原文になじんでいると、新しく加えられた主張を既存の内容と誤認しやすい。 |
| 置換 | 語句の変更によって意味の範囲や判断主体が変わっていないかを確認する。 | 同義語に見える表現でも、確実性、時期、対象範囲が変わる場合がある。 |
| 並べ替え | 前提、根拠、結論の順序が保たれているかを確認する。 | 段落単体では自然でも、根拠より先に結論が現れ、論理の依存関係が崩れる場合がある。 |
Undo と差分表示は、同じ変更を異なる時間軸で扱う。差分表示は採用前に元の版と候補を比較する。Undo は採用後に、実際のバッファ変更を取り消す。差分を確認して採用した後でも、後続の編集や周辺箇所との不整合が判明すれば元へ戻せる。生成結果を一度の判断で確定させず、比較、試用、撤回を繰り返せることが、通常の編集環境へ AI を置く具体的な利点になる。
ただし、差分が示すのは文字列の変化であり、変更の正しさではない。ある条件が削除されたことは見えるが、その条件が不要かどうかは差分からは決まらない。関数の行数が減ったことは確認できても、外部から期待される動作が維持されたかは別の検査が必要になる。差分表示は採用判断に必要な証拠を増やすが、判断を代行する機能ではない。
3.2 診断と実行結果も同じ環境で確認できる
文字列の差分を確認した後には、変更後の内容が実際に成立するかを確かめる必要がある。Emacs の compilation-mode は外部コマンドを実行し、標準出力と標準エラー出力を専用バッファへ集め、認識できるエラー表示から該当位置へ移動する仕組みを持つ[13]。生成された変更を保存した後、構文検査、試験、文書変換、静的解析を同じ Emacs セッションから実行し、失敗した行へ戻れる。
この経路では、確認が二段階に分かれる。最初に差分を読み、削除や追加が意図した範囲に収まっているかを確認する。次に、機械的な検査を実行し、構文や既知の試験条件を満たしているかを確認する。差分だけでは、変更後のコードが実行できるかは分からない。試験結果だけでは、試験対象に含まれない条件が失われていないかは分からない。人間による変更内容の確認と、機械による成立条件の確認は、検出できる失敗の種類が異なる。
| 検査段階 | Emacs で使える手段 | 検出できること | 検出できないこと |
|---|---|---|---|
| 入力範囲の確認 | リージョン、バッファ、追加ファイル、送信要求の確認を使う。 | どの文字列や資料をモデルへ渡すかを限定できる。 | 選択した文脈だけで判断に必要な前提がそろうかは決まらない。 |
| 文字列差分の確認 | 差分表示、Ediff、Undo を使う。 | 追加、削除、置換、移動された箇所を特定できる。 | 変更後の主張や処理が要件に適合するかは決まらない。 |
| 機械的な成立確認 | compilation-mode、診断機能、外部コマンドを使う。 | 構文エラー、変換失敗、既知の試験条件への違反を検出できる。 | 試験されていない条件、事実関係、設計判断の妥当性は検出できない。 |
| 成果物への採用 | 保存、部分採用、追加修正、Undo を使う。 | 候補を正式な内容へ反映し、必要なら撤回できる。 | 採用された内容の責任や後続影響が AI へ移るわけではない。 |
検査経路を Emacs 内へ置く利点は、AI が正しさを保証することではなく、生成結果から失敗箇所へ戻る距離を短くできる点にある。試験が失敗した場合、出力に表示されたファイル名と行番号から対象バッファへ移動し、差分を確認し、修正して再実行できる。別のアプリケーションで生成し、別の端末で試験し、さらに別の画面で対象ファイルを探す構成に比べ、生成、確認、修正、再実行の対応関係を保ちやすい。
一方、Claude Code などの外部プロセスがファイルを書き換える構成では、ディスク上の内容と Emacs のバッファが自動的に一致するとは限らない。外部プロセスが保存済みファイルを更新しても、Emacs が変更前の内容を表示し続ければ、人間は古い版に対して差分確認や追加編集を行うことになる。Auto Revert は外部変更を検出してバッファを読み直す機能を提供するが、未保存の変更がある場合や監視方法によって再読込の条件は変わる[14]。
この不一致は、AI が誤った変更をした場合だけに生じるものではない。外部プロセスがディスク上の版を正しく更新しても、Emacs が変更前のバッファを表示していれば、画面上の内容、試験に使われた内容、保存されている内容が三つに分かれる。生成結果の検査には、変更内容に加えて、どの版を見ているかの確認が必要になる。
| 状態 | Emacs のバッファ | ディスク上のファイル | 起こり得る帰結 |
|---|---|---|---|
| 外部変更なし | 現在の編集内容を保持している。 | 最後に保存した内容を保持している。 | 未保存変更の有無だけを確認すればよい。 |
| 外部プロセスが更新 | 更新前の内容を表示している場合がある。 | AI が変更した新しい内容を保持している。 | 古い表示を基準に確認し、外部変更を上書きする可能性がある。 |
| 人間にも未保存変更がある | 人間が加えた未保存内容を保持している。 | 外部プロセスが別の変更を保存している。 | 単純な再読込ではどちらかの変更を失うため、比較と統合が必要になる。 |
| 再読込後 | ディスク上の新しい内容を表示する。 | 外部プロセスが保存した内容と一致する。 | 表示対象はそろうが、変更の妥当性は別途確認する必要がある。 |
Emacs の編集機能と診断機能を同じ環境で使えることは、生成結果を無条件に信頼できるという意味ではない。差分、試験、外部変更の検出は、それぞれ異なる失敗を見つける。どれか一つが成功しても、他の条件まで満たされたとは限らない。AI の出力を採用可能な候補へ進めるには、文字列の変化、機械的な成立、表示している版の一致を別々に確認する必要がある。
3.3 会話を通常の文書として扱える
gptel の会話は、Org、Markdown、Text などの通常バッファとして保存できる[6]。質問と回答は専用サービスの履歴画面に固定されず、見出しを付け、不要な往復を削り、検索し、別の文書へ必要部分を移せる。対話中の回答を読むだけでなく、後から参照する調査記録、判断過程、文章素材として編集できる。
通常の文書として保存できることは、会話の整理方法を Emacs 側で決められることを意味する。質問と回答のうち後から必要になる部分を残し、試行錯誤や重複した往復を削除したうえで、検索可能な記録として保存し、別の文章や後続の会話へ再利用できる。サービス側の会話一覧に依存せず、通常のファイル管理、検索、バックアップの対象へ移せる点が利点になる。
ただし、保存した会話文書は、その時点でモデルへ送られた要求全体の完全な記録とは限らない。画面に表示された質問と回答のほかに、システム指示、追加したファイル、過去の会話、ツール定義、画像、選択中のモデル、モデル固有の設定が要求へ加わる場合がある。会話文書だけを読み直しても、同じ回答を再現するために必要な条件がすべて残っているとは限らない。
| 情報の種類 | 会話文書から確認しやすいこと | 別に確認が必要なこと |
|---|---|---|
| 質問と回答 | 表示された入力、出力、修正の往復を確認できる。 | 表示前に内部で追加された指示や変換処理は文書だけでは分からない場合がある。 |
| 追加文脈 | 本文中に明示して残した資料名や説明を確認できる。 | 一時的に追加されたバッファやファイルの内容が保存文書へ含まれない場合がある。 |
| モデル設定 | 会話中に明記したモデル名や条件を確認できる。 | 温度、文脈長、接続先固有の設定が別の構成に保存される場合がある。 |
| ツール実行 | 回答中に記録された実行結果を確認できる。 | 実行時の引数、権限、外部状態、取得元が完全には残らない場合がある。 |
| 編集後の会話 | 不要な往復を削り、読みやすい記録へ整えられる。 | 後から編集した文書と、実際に行われた会話の履歴が一致しなくなる。 |
会話を編集できることは、記録としての価値と再現性の間に緊張を生む。不要な回答を削り、見出しを追加し、文章を整えれば、後から読みやすい資料になる。一方で、質問の順序や失敗した試行を削除すると、どの前提から最終回答へ到達したかを追えなくなる。成果物の素材として整理する文書と、対話過程を保存する記録では、残すべき情報が異なる。
同じ会話ファイルを両方の用途へ使う場合、編集によって履歴の意味が変わる。モデルの回答を修正した後に会話を再開すれば、画面上では修正版が過去の回答として見える場合がある。しかし、その修正文をモデル自身が生成したわけではない。保存文書を成果物として整える操作と、過去の対話を証拠として保存する操作を区別しなければ、後から人間が加えた内容とモデルが出力した内容の境界が曖昧になる。
通常バッファで会話を扱えることは、専用の履歴画面より高い編集自由度を与える。その自由度は、会話を調査記録、文章素材、再利用可能な指示へ変換する場合に有効である。反対に、同じ条件での再実行や過去の判断経路の検証を求める場合には、表示された会話だけでなく、追加文脈、モデル設定、ツール実行、編集履歴まで保存対象を広げる必要がある。
生成と採用の間に検査点を置けるという Emacs の利点は、差分表示だけで成立するものではない。生成結果を変更候補として受け取り、元の版と比較し、機械的な検査を実行し、表示している版を確定し、必要な会話記録を残す。この一連の操作を同じ編集環境で行えることで、AI の回答をその場で消費する対話から、検査と撤回が可能な編集工程へ移せる。Emacs が提供するのは正しさの保証ではなく、候補が正式な内容へ変わるまでに、人間が確認できる地点を増やす仕組みである。
4. 対話画面の忠実性と Emacs の入力編集性には交換関係がある
4.1 ターミナル内包型は Claude Code の操作を保ちやすい
claude-code.el は、Claude Code の対話画面を独自の Emacs バッファへ置き換えるのではなく、eat、vterm、ghostel などのターミナル実装上で Claude Code CLI を動かす。Claude Code が表示する進行状況、選択肢、許可確認、対話コマンドを保ちながら、現在のファイル、カーソル位置、選択範囲を Emacs 側から送信できる。処理の表示と操作は Claude Code の対話画面に残り、Emacs はその画面を収容し、編集対象との受け渡しを補助する[3]。
この構成では、Claude Code 固有の状態を失いにくい。処理中に実行している内容、確認待ちの操作、入力可能な選択肢が同じ画面に表示されるため、回答文だけを通常バッファへ転記する方式より、現在の進行状況を把握しやすい。Claude Code が端末制御文字で更新した画面をターミナル実装が Emacs 内へ描画するため、Claude Code が想定する対話の流れを大きく変えずに利用できる。
一方、ターミナル画面の再現性は、Claude Code と Emacs だけでは決まらない。使用するターミナル実装によって、描画速度、ネイティブモジュールの要否、Unicode 罫線、色表示、画面幅、スクロールバック、クリップボード連携、キー転送の挙動が変わる。Claude Code の公式文書でも、改行キー、通知、tmux 内のキー転送など、端末設定が操作へ影響することが説明されている[15]。Emacs 内へ画面を置くことで端末依存が消えるのではなく、端末に由来する条件を Emacs の設定と依存関係として引き受けることになる。
ターミナル内包型の利点は、Claude Code の対話状態を通常の文章へ変換せず、そのまま操作できることにある。反対に、表示や入力の不具合が生じた場合には、Claude Code 自体の問題と、ターミナル描画や Emacs のキー処理の問題を分けて確認しなければならない。同じ「入力できない」という現象でも、Claude Code が確認待ちである場合、ターミナルがキーを転送していない場合、Emacs のコマンドが先に入力を取得している場合では修正箇所が異なる。
4.2 通常バッファと対話型ターミナルは入力経路が違う
通常バッファでは、押されたキーを最初に Emacs が受け取り、コマンドとして実行するか、入力メソッドで変換して文字として挿入するかを決める。検索、置換、Undo、キルリング、補完、ddSKK や Quail による日本語入力は、この処理経路を前提としている。文字列は Emacs が管理するバッファへ入り、送信されるまで通常の編集対象として保持される。
対話型ターミナルでは、矢印、Enter、Esc、Control キーを Claude Code へ届けなければ、候補選択、送信、中断、対話画面固有の操作が成立しない。ターミナル実装がキー入力を端末用の入力列へ変換し、Claude Code が対話操作として解釈する。Emacs がキーを通常コマンドとして処理すると Claude Code には届かず、反対にすべてのキーを子プロセスへ渡すと Emacs の通常操作を実行できなくなる。
この競合は、同じキーに異なる意味が割り当てられることで起きる。たとえば、Emacs ではバッファ移動や編集に使うキーが、Claude Code 側では候補選択や中断に使われる場合がある。ターミナルへ入力を優先的に渡す状態では Emacs の編集操作が使いにくくなり、Emacs 側の操作へ戻すと Claude Code の対話画面を直接操作できなくなる。どちらか一方の処理体系へ統一するのではなく、入力先を切り替えながら利用する構成になる。
claude-code.el が通常バッファから選択範囲やファイルを送る機能を持つのは、この入力差を補うためである。長い指示や修正対象は通常バッファで整え、Claude Code 固有の選択や許可確認はターミナル画面で行う。読み取り専用の状態へ切り替えて通常の選択とコピーを行う機能も、ターミナル画面を通常バッファと同じものへ変えるのではなく、閲覧時だけ Emacs の操作を優先させる。
| 操作 | 通常バッファ | ターミナルバッファ | 切り替えが必要になる理由 |
|---|---|---|---|
| 長文入力 | 入力メソッド、検索、置換、Undo を使って編集できる。 | 子プロセスへ入力を渡しながら編集するため、通常の編集機能を使いにくい。 | 文章編集と対話画面操作では、最初にキーを処理すべき主体が異なる。 |
| 候補選択 | 通常の文章には Claude Code 固有の選択状態がない。 | 矢印や対話コマンドで Claude Code の候補を直接選べる。 | 候補の状態は Claude Code のプロセス内にあり、通常バッファでは再現されない。 |
| 許可確認 | 許可要求を文章として表示できても、対話状態そのものは保持しない。 | Claude Code が待機している状態へ直接回答できる。 | 許可要求は単なる出力文ではなく、外部プロセスが入力を待つ実行状態である。 |
| 選択とコピー | リージョンとして通常の編集操作を利用できる。 | マウス操作や端末固有の選択と競合する場合がある。 | ターミナル画面は文字列だけでなく、カーソル位置と画面状態を保持している。 |
ターミナル内包型は、Claude Code の対話操作と Emacs の編集操作を完全に統合するものではない。Claude Code 固有の状態を扱うときはターミナルとして操作し、長い指示の編集や回答の再利用では通常バッファへ移る。二つの操作体系を行き来する負担を受け入れる代わりに、Claude Code の対話画面を失わずに Emacs 内へ置ける。
4.3 通常バッファを仲介すると画面と履歴が二重化する
zellij-send.el は、Claude Code の画面を Emacs 内のターミナルとして直接動かさない。通常バッファで指示を完成させ、その文字列を Zellij の特定ペインへ送る。Zellij は、切り離されたセッションの作成、対象ペインを指定した入力、表示中の画面内容の取得、画面更新の購読を提供する[16]。Emacs は文字列の編集と閲覧を担当し、Claude Code の実行状態は Zellij のペインに残る。
この構成では、キー入力を Claude Code へ逐次転送する必要がない。Emacs が通常の文字列として確定した指示文を、zellij-send.el が外部ペインへ送るため、Emacs の入力メソッドや編集操作を維持できる。対話画面で要求される Esc、Enter、選択操作などは、専用コマンドや明示的なキー転送として別に扱う。
入力経路を分けることで、表示と履歴も一つには保てなくなる。Zellij から取得できるのは、基本的にその時点でペインへ表示されている画面である。長い回答や実行結果が画面上方へ流れれば、現在画面の取得だけでは会話全体を復元できない。Claude Code が長い貼り付けを画面上で省略表示した場合も、表示された一画面から元の入力全文を読み直すことはできない。
zellij-send.el は、この制約に対して二つの経路を使う。進行中の状態を確認するときは Zellij の画面を取得し、Claude Code が現在何を表示しているかを通常バッファへ転写する。会話全体を読み直すときは、Claude Code が保存したセッション記録を解析し、質問と回答を通常バッファへ再構成する。現在画面は即時性を持つが一画面分に限られ、セッション記録は全履歴を持つが、現在のカーソル位置や選択中の候補までは再現しない。
| 情報源 | 確認できる内容 | 確認できない内容 | ずれが生じる条件 |
|---|---|---|---|
| Zellij の現在画面 | Claude Code が現在表示している進行状況、確認要求、直近の回答を確認できる。 | 画面外へ流れた過去の回答や、省略表示された長文の全体は確認できない。 | 長い出力、画面更新、ウィンドウ幅の変更によって過去の内容が表示範囲外へ移る。 |
| Claude Code のセッション記録 | 過去の質問、回答、ツール実行の記録を時系列で再構成できる。 | 現在選択中の候補、カーソル位置、画面上の一時的な表示状態は再現しない。 | 画面上では確認待ちでも、記録側には確定前の一時状態が残らない場合がある。 |
| Emacs の入力バッファ | 送信前の指示、未送信の修正、Emacs の入力履歴を保持できる。 | 外部ペインがその文字列を受理し、どの時点で処理を始めたかは単独では分からない。 | 送信中の失敗、対象ペインの誤指定、未送信文字列の残存によって対応が崩れる。 |
| 作業対象のファイル | Claude Code が保存した変更結果を確認できる。 | どの表示や会話がその変更を生んだかはファイルだけでは分からない。 | 複数セッションが同じ作業対象を扱うと、会話と変更結果の対応を追いにくくなる。 |
画面取得と履歴再構成の二重化は、同じ情報を冗長に保存するためのものではない。全画面型の対話プログラムでは、現在の操作状態と、後から読み直せる会話記録が異なる形式で存在する。現在の確認要求へ回答するには画面が必要であり、前の回答を検索して再利用するにはセッション記録が必要になる。どちらか一方だけでは、対話操作と文章閲覧の両方を満たせない。
この方式では、入力バッファの自動更新にも制約が生じる。外部画面を定期的に転写すると、まだ送信していない指示文を上書きする可能性がある。そのため、入力中は自動更新を止め、現在画面を確認するときに再取得する設計が必要になる。未送信文字列を保護する間は外部状態の反映が遅れ、Emacs 上の表示が Zellij の現在画面より古くなる時間が生じる。
| 観点 | claude-code.el | zellij-send.el | 選択時に引き受ける条件 |
|---|---|---|---|
| 対話画面 | Claude Code の画面をターミナルとして直接表示する。 | 外部ペインの現在画面を通常バッファへ転写する。 | 直接表示ではターミナルの入力制約を、転写では表示遅延と状態同期を引き受ける。 |
| Emacs の入力メソッド | 通常バッファから送る場合は使えるが、ターミナル欄への直接入力では制約を受ける。 | 通常バッファで指示を作成するため利用しやすい。 | 入力編集を優先するほど、対話画面への直接操作は専用コマンドへ分かれる。 |
| Claude Code 固有の操作 | 許可確認、選択肢、対話コマンドを画面上で直接扱える。 | 画面取得後にキー転送や専用操作を行う。 | 忠実な操作を優先するか、通常バッファによる編集を優先するかを選ぶ。 |
| 全会話の閲覧 | ターミナルのスクロールバックと Claude Code のセッションに依存する。 | Claude Code のセッション記録から通常バッファへ再構成する。 | 現在画面と全履歴が別の情報源になることを管理する。 |
| 処理の継続 | Emacs 内のターミナルと Claude Code のプロセスを維持する。 | Zellij の切り離されたセッションが残れば Emacs の表示と独立して継続する。 | 継続性を高めるほど、外部セッションの識別と再接続が必要になる。 |
| 構成要素 | Emacs、claude-code.el、Claude Code、ターミナル実装で構成する。 | Emacs、zellij-send.el、Claude Code、Zellij、必要に応じて通知用フックで構成する。 | 外部セッション仲介型は入力の自由度と継続性を得る代わりに、管理する接続点が増える。 |
claude-code.el と zellij-send.el の差は、Claude Code をどこに表示するかだけではない。claude-code.el は、Claude Code の対話状態をターミナル画面ごと Emacs 内へ置く。zellij-send.el は、指示作成と履歴閲覧を通常バッファへ移し、対話状態と実行プロセスを Zellij に残す。前者は画面と操作の忠実性を優先し、後者は入力編集と実行継続を優先する。
Claude Code の許可確認や対話コマンドを頻繁に操作する場合は、ターミナル内包型の直接性が有効になる。長い日本語の指示を Emacs の入力機能で整え、別の編集を続けながら複数の処理を動かす場合は、外部セッション仲介型に利点がある。どちらの方式でも、Claude Code の操作性と Emacs の編集性を同じ強さで同時に得られるわけではない。保持したい操作を一方へ寄せることで、もう一方に必要な切り替え、同期、履歴管理が増える。
5. バックグラウンド継続は状態を複数箇所へ分ける
5.1 表示中の Emacs から処理を切り離せる
Emacs は外部プログラムをサブプロセスとして起動し、その標準入力、標準出力、終了状態をバッファへ結び付けられる[17]。非同期プロセスを使えば、外部処理の完了を待つ間も、別のバッファで編集や検索を続けられる[18]。gptel の逐次応答や、Emacs 内のターミナルで動く Claude Code も、表示を止めずに外部処理の結果を受け取るという点では、この仕組みの上にある。
非同期処理は画面の占有を避けられるが、それだけで Emacs から独立するわけではない。Emacs が起動したサブプロセスは、処理中に別のバッファへ移動できても、Emacs プロセスの終了、接続バッファの破棄、ターミナル実装の停止によって影響を受ける場合がある。処理の寿命は、Emacs の寿命やバッファの状態に結び付いたまま残る。
Zellij を介する方式では、実行プロセスを Emacs のサブプロセスからさらに外側へ置く。Zellij は端末を接続していない切り離し状態でもセッションを維持し、外部から特定のセッションやペインへ入力を送り、画面内容を取得できる[19]。Emacs は指示と表示の窓口になるが、Claude Code の実行そのものは Zellij のセッション内で続く。
この配置によって、Emacs のウィンドウを閉じ、別の作業へ移り、後から対象セッションへ戻ることができる。複数の Claude Code を別々の Zellij セッションで動かせば、一つの対話が完了するまで他の作業を止める必要もない。表示領域の占有を避けるだけでなく、AI の処理時間と人間の編集時間を並行させられる。
実行を画面から切り離すと、進行状況の把握は間接的になる。Emacs 内のダッシュボードが「作業中」や「完了」と表示していても、その状態は外部ペインの画面内容、最終更新時刻、特定の表示文字列などから判定した結果である。Claude Code が外部ペインを更新し、zellij-send.el が画面を取得して状態を分類するまでには、実際の処理と表示の間に時間差が生じ得る[5]。
| 実行配置 | 別作業との並行 | Emacs 終了時の扱い | 進行状況の確認 | 主な管理負担 |
|---|---|---|---|---|
| 同期処理 | 処理の完了まで同じ操作経路が占有される。 | Emacs の終了とともに処理も失われやすい。 | 現在のバッファに表示される出力を直接確認する。 | 構成は単純だが、待ち時間を別作業へ使いにくい。 |
| Emacs の非同期サブプロセス | 別のバッファへ移動して編集を続けられる。 | プロセスの寿命が Emacs や接続バッファに依存する場合がある。 | プロセスバッファ、ターミナルバッファ、フィルター出力から確認する。 | バッファと外部プロセスの対応を管理する必要がある。 |
| Zellij の切り離しセッション | Emacs の表示状態と独立して複数の処理を継続できる。 | Zellij セッションが残れば Emacs の再起動後も処理を継続できる。 | 画面取得、通知、ダッシュボード、再接続によって確認する。 | セッション名、ペイン、作業対象、履歴の対応付けが必要になる。 |
バックグラウンド継続の利点は、処理を見なくてよくなることではない。処理の実行場所と、利用者が現在編集している場所を分離できる点にある。分離後も進行状況を判断するには、どのセッションがどの作業を担当し、最後にいつ状態が更新されたかを追跡できなければならない。
5.2 Emacs の再起動と AI 処理の継続は別である
Emacs を再起動した後も Claude Code の処理が続いているかは、Claude Code をどこで動かしていたかによって決まる。Emacs 内のターミナルで起動したプロセスは、通常、その Emacs セッションとともに失われる。一方、Zellij の切り離しセッションで起動したプロセスは、Emacs が終了しても Zellij 自体が動作していれば継続する。zellij-send.el は、再起動後の Emacs から既存セッションを再検出し、対応するペインへ再接続できる[5]。
ここで区別すべきなのは、実行中プロセスの継続と、終了したセッションの再構成である。実行中の Zellij セッションへ再接続する場合、Claude Code のプロセス、対話状態、現在の作業はそのまま残っている。Zellij のセッション復元機能(Session Resurrection)は、終了後に保存された配置や起動コマンドを使って画面構成を復元する機能であり、以前のプロセスを時間的に継続させるものではない。安全上の理由から、復元されたコマンドは自動的には実行されない[20]。
| 再開の種類 | 残っているもの | 失われているもの | 再開時に必要な操作 |
|---|---|---|---|
| 実行中セッションへの再接続 | Claude Code のプロセス、現在の対話状態、外部ペインの画面が残っている。 | Emacs 側のバッファ表示や一時的な入力状態は失われる場合がある。 | 既存の Zellij セッションと対象ペインを再検出し、Emacs バッファへ対応付ける。 |
| 保存された配置の復元 | ペイン配置、作業ディレクトリ、起動コマンドなどの構成情報が残る。 | 以前のプロセス状態、未完了の対話、メモリー上の実行状態は残らない。 | 復元されたコマンドを確認し、必要なものだけを明示的に再実行する。 |
| Claude Code の会話再開 | 保存された会話記録やセッション情報を読み直せる。 | 終了時点の端末画面、実行中だった一時状態、未保存の外部変更は再現されない場合がある。 | 対応する会話記録を選び、現在のファイル状態との差を確認してから処理を再開する。 |
外部処理の完了を Emacs へ知らせる場合には、逆方向の接続が必要になる。Emacs server を起動すると、外部プログラムから既存の Emacs プロセスへ接続できる[21]。emacsclient は、その接続を使ってファイルを開き、Emacs Lisp 式を評価し、既存バッファの更新を依頼する[22]。
zellij-send.el の自動受信では、Claude Code の完了時フックが emacsclient を呼び、対応する Emacs バッファへ再取得や更新を要求する[5]。処理経路は、Claude Code の完了、フックの発火、emacsclient の起動、Emacs server への接続、対象バッファの特定、画面または履歴の再取得という複数段階になる。Claude Code が正常に処理を終えていても、この途中の一か所で失敗すれば Emacs 側は更新されない。
| 経路 | 正常時の動作 | 失敗時の見え方 | 確認対象 |
|---|---|---|---|
| Claude Code の完了 | 処理を終え、完了イベントを発生させる。 | 外部ペインでは完了しているが、後続の通知が始まらない。 | Claude Code の状態とフックが発火する条件を確認する。 |
| 完了時フック | emacsclient を所定の引数で起動する。 | 処理は完了しているが、Emacs には何も通知されない。 | フック設定、実行権限、環境変数、emacsclient のパスを確認する。 |
| emacsclient | 既存の Emacs server へ接続し、更新処理を依頼する。 | 接続エラーが発生するか、別の Emacs セッションへ接続する。 | Emacs server の起動状態、ソケット、サーバー名を確認する。 |
| Emacs 側の更新処理 | 対象セッションに対応するバッファを再取得して表示を更新する。 | 通知は届くが、別のバッファが更新されるか、古い内容が残る。 | セッション識別子、対象バッファ、画面取得、履歴再構成を確認する。 |
自動更新が失敗しても、AI 処理そのものが失敗したとは限らない。外部ペインを直接確認すれば処理が完了している場合もある。反対に、完了通知が表示されても、対象ファイルへの変更や会話記録の保存まで正常に終わったとは限らない。実行結果と通知結果は、同じ成功条件としてまとめずに確認する必要がある。
5.3 バッファ、画面、プロセス、履歴、ファイルは同じ状態ではない
外部セッションを Emacs から操作すると、利用者が一つの作業として認識している内容が、複数の場所へ分かれて保存される。指示は Emacs の入力バッファにあり、現在の進行状況は Zellij のペインにあり、会話全体は Claude Code の記録にあり、変更結果はディスク上のファイルにある。これらは同時に更新されず、同じ時点の状態を示すとも限らない。
不一致は、更新主体が異なることから生じる。第 1 段階で利用者が Emacs バッファへ指示を書く。第 2 段階で zellij-send.el がその文字列を外部ペインへ送る。第 3 段階で Claude Code がファイルを読み、処理し、画面と会話記録を更新する。第 4 段階で Emacs が画面や履歴を再取得する。この途中で人間が対象ファイルを編集したり、別のセッションが同じファイルを変更したりすれば、AI が読んだ内容、現在のファイル、Emacs が表示している内容は一致しなくなる。
| 状態 | 主な保持場所 | 更新する主体 | 最新であることを確認する方法 | 起こり得る不一致 |
|---|---|---|---|---|
| 送信前の指示 | Emacs の通常バッファ | 利用者 | 未送信文字列と送信履歴を確認する。 | 送信済みの指示と、その後に修正した未送信の文章を取り違える。 |
| 現在の対話画面 | Claude Code のターミナルまたは Zellij のペイン | Claude Code とターミナル | 対象ペインの現在画面を直接取得する。 | Emacs 側の転写が遅れ、確認待ちや完了後の表示を見落とす。 |
| 会話全体 | gptel の会話文書または Claude Code の記録 | AI クライアントと利用者 | セッション識別子と記録の最終更新時刻を確認する。 | 別のセッションの履歴を読み、現在の作業の前提と誤認する。 |
| 実行状態 | Emacs のサブプロセスまたは Zellij セッション | OS と外部プログラム | プロセス一覧、Zellij セッション一覧、終了状態を確認する。 | 画面更新が止まっただけなのに、処理自体が停止したと判断する。 |
| Emacs の編集内容 | 未保存の Emacs バッファ | 利用者と Emacs | 変更済み表示とディスク上のファイルとの差を確認する。 | AI が読んだ保存済みファイルと、利用者が見ている未保存内容が異なる。 |
| ディスク上のファイル | 作業ディレクトリ | 利用者、Emacs、Claude Code、別の外部処理 | 更新時刻、差分、Emacs バッファとの一致を確認する。 | 別のセッションによる変更を、現在の会話が生成した結果と誤認する。 |
| 通知状態 | Emacs、デスクトップ通知、完了時フック | 外部プロセスと連携処理 | 外部ペインの状態と通知履歴を照合する。 | 処理は完了していても通知だけが失敗し、作業中と判断し続ける。 |
時間差だけでなく、識別子の不一致も状態をずらす。複数の Zellij セッションを動かす場合、Emacs バッファ名、Zellij のセッション名、ペイン ID、作業ディレクトリ、Claude Code の会話記録が一対一で対応していなければならない。どれか一つを再利用したり、セッション名だけで別の処理を判断したりすると、別の会話へ指示を送り、別の履歴を読み、別のファイル変更を確認する可能性がある。
複数セッションのダッシュボードは、この分散した状態を一つへ戻すものではない。セッション名、作業ディレクトリ、最終更新時刻、現在画面、完了表示を並べ、どの状態を確認すべきか判断するための索引である。表示上の「完了」は、通知や画面判定が完了したことを示しても、ファイル変更の妥当性、未保存バッファとの競合、会話記録の対応まで保証しない。
バックグラウンド継続によって得られるのは、AI の処理を待たずに別の編集を進められる時間である。その時間は、処理、画面、履歴、ファイルを別々に維持する構造によって作られる。長時間処理や複数セッションを安定して扱うには、常に一つの最新状態が存在すると考えるのではなく、どの状態を、どの主体が、いつ更新したかを確認できる構成が必要になる。
6. 統合層を増やすほど保守対象と障害点も増える
6.1 三方式では依存する構成要素が異なる
Emacs から AI を利用する三方式は、同じ数の構成要素を異なる画面で操作しているわけではない。gptel は Emacs から接続先 API へ直接要求を送るため、主な接続点は Emacs パッケージ、認証情報、モデル名、通信先である。claude-code.el は、この経路に Claude Code CLI とターミナル実装を加える。zellij-send.el では、さらに Zellij のセッションとペイン、画面取得、会話記録、完了時フック、Emacs server が処理経路へ入る。
構成要素が一つ増えると、設定項目が一つ増えるだけでは済まない。新しい要素を起動して既存の要素へ接続し、モデル名、セッション名、ペイン ID、ソケット、作業ディレクトリなどを処理中も対応付ける必要がある。各要素の更新によって入出力形式や起動条件が変われば、接続部分の互換性も確認対象になる。
gptel の接続先をクラウド API とする場合、認証情報の取得方法、接続先 URL、利用可能なモデル名、要求形式が一致していなければならない。Ollama へ接続する場合には、API キーの代わりに、Ollama の起動状態、待ち受け先、取得済みモデル、モデル名の表記が条件になる。通常バッファ上では同じ送信操作に見えても、接続先が変われば故障条件も変わる。
claude-code.el では、Claude Code の実行ファイルが存在するだけでは動作条件がそろわない。Claude Code を表示する eat、vterm、ghostel などのターミナル実装が必要になり、その実装が端末制御、キー転送、画面幅、文字表示を正しく扱う必要がある。Claude Code が正常に回答を生成していても、ターミナルが画面を正しく描画できなければ、利用者には表示障害として現れる。
zellij-send.el では、Claude Code が動くこと、Zellij セッションが残っていること、対象ペインを特定できること、Emacs から入力を送れること、外部画面を取得できることが別々の条件になる。完了時に自動更新する構成では、Claude Code のフックが emacsclient を起動し、正しい Emacs server へ接続し、対応するバッファを更新するところまで成功しなければならない[5]。外部処理の完了と Emacs 上の表示更新は、一つの成功条件ではない。
Claude Code の設定は、利用者全体へ適用する設定、プロジェクトで共有する設定、端末固有の設定、管理者が強制する設定など、複数の範囲を持つ。許可規則、環境変数、利用可能なツールは、どの範囲へ記述したかによって適用対象が変わる[23]。Emacs から同じ Claude Code を起動しても、作業ディレクトリや設定範囲が違えば、許可される操作や読み込まれる設定は同一にならない。
フックを追加すると、Claude Code の開始、ツール実行の前後、通知、停止などの時点で、別のコマンドや処理を起動できる[24]。完了時に Emacs のバッファを更新する処理は、この仕組みを利用できる。一方、フックは Claude Code の外側へ新しい実行経路を作るため、環境変数、実行権限、標準入力、終了状態、タイムアウトも保守対象に加わる。
| 方式 | 処理経路に入る主な層 | 識別に必要な情報 | 更新時に確認する接続点 | 構成が増えることで生じる負担 |
|---|---|---|---|---|
| gptel | Emacs、gptel、クラウド API またはローカル API、モデルで構成する。 | 接続設定名、接続先、認証情報、モデル名、追加文脈を識別する。 | gptel の要求形式、API の仕様、モデル名、認証方法の一致を確認する。 | 通信経路は短いが、画面に見えない要求設定と接続先の差を管理する必要がある。 |
| claude-code.el | Emacs、claude-code.el、Claude Code、ターミナル実装で構成する。 | Claude Code のセッション、作業ディレクトリ、ターミナルバッファを識別する。 | Claude Code の起動方法、対話画面、キー転送、端末描画の互換性を確認する。 | Claude Code の処理とターミナル表示のどちらで故障したかを分ける必要がある。 |
| zellij-send.el | Emacs、zellij-send.el、Claude Code、Zellij、会話記録、必要に応じてフックと Emacs server で構成する。 | Emacs バッファ、Zellij セッション名、ペイン ID、作業ディレクトリ、会話記録を対応付ける。 | 入力送信、画面取得、履歴再構成、完了通知、emacsclient 接続を個別に確認する。 | 継続性と入力編集性を得る代わりに、状態を結ぶ識別情報と通知経路が増える。 |
| MCP 追加時 | 各方式に MCP クライアント、MCP サーバー、外部サービスを加える。 | サーバー名、接続方法、認証情報、公開されるツール、操作対象を識別する。 | プロトコル、サーバー起動、ツール定義、認証、接続先 API の互換性を確認する。 | 会話経路とは別に、外部システムを読み書きする実行経路を保守する必要がある。 |
三方式の違いは、導入時の設定量だけでは評価できない。gptel は接続経路が短いため障害点を限定しやすいが、要求へ含まれる追加文脈やモデル設定を Emacs 側で確認する必要がある。claude-code.el は Claude Code の画面を直接扱える代わりに、CLI とターミナルの境界を保守する。zellij-send.el は処理を Emacs から切り離せる代わりに、外部セッションと Emacs バッファの対応関係を長期間維持しなければならない。
6.2 同じ症状でも故障箇所は一つではない
「返答が来ない」「表示が更新されない」「ファイルが変わらない」といった現象は、利用者から見れば一つの失敗に見える。しかし、統合された画面へ結果が現れるまでには、入力、通信、実行、表示、履歴、通知という複数の段階がある。上流の処理が成功していても、下流の表示だけが失敗すれば、画面上では全体が停止したように見える。
gptel で返答が表示されない場合、最初に接続先 API が単体で応答するかを確認する。接続先が応答するなら、認証情報、モデル名、gptel の接続先設定へ範囲を狭められる。接続先自体が応答しない場合には、Emacs のバッファ処理を調べても原因には届かない。接続先 API の動作を確定してから Emacs の要求との差を調べれば、外部サービスと Emacs 設定を分離できる。
ローカルモデルが利用できない場合には、Ollama のプロセス、11434 番ポート、モデル一覧、モデルファイル、gptel のモデル名を順に確認する。Ollama API がモデル一覧を返さなければ、gptel の表示設定を変更してもモデルは現れない。API は応答するが指定したモデルだけが見つからない場合には、モデルの取得状態または名称の不一致を確認する。回答が返るが遅い場合には、接続設定ではなく、モデルの読み込み、端末資源、入力長が候補になる。
Claude Code の画面が崩れる場合、Claude Code が出力した内容と、Emacs 内のターミナルが描画した結果を分ける必要がある。外部の端末では正常に表示できるなら、Claude Code 自体より、eat、vterm、ghostel の画面幅、文字描画、端末機能を確認する。外部端末でも同じ崩れ方をするなら、Claude Code の画面出力や端末環境全体へ確認範囲を戻す。
zellij-send.el が更新されない場合には、Zellij の対象ペインを直接確認する。ペイン内で Claude Code がまだ処理中なら、Emacs の自動更新は故障していない。ペインでは完了しているのに Emacs へ反映されない場合、画面取得、完了時フック、emacsclient、Emacs server、対象バッファの識別へ確認を進める。外部画面の状態を先に確定しなければ、処理の遅延と通知経路の故障を区別できない。
| 観察される現象 | 第 1 の確認 | 第 2 の確認 | 第 3 の確認 | 確認順を誤った場合 |
|---|---|---|---|---|
| gptel が返答しない | 接続先の API が単体で応答するかを確認する。 | 認証情報、接続先、モデル名が一致しているかを確認する。 | Emacs のメッセージ、要求送信、非同期応答処理を確認する。 | 接続先が停止しているのに Emacs の表示設定だけを変更し続ける。 |
| ローカルモデルを選択できない | Ollama が起動し、API が応答するかを確認する。 | 取得済みモデルの一覧と正確なモデル名を確認する。 | gptel の接続先設定とモデル登録を確認する。 | モデルが端末に存在しない状態で Emacs 側の候補表示だけを調整する。 |
| Claude Code の表示が崩れる | 外部端末で同じ Claude Code を表示して比較する。 | Emacs 内のターミナル実装と画面幅を確認する。 | フォント、Unicode 表示、キー転送、スクロールバックを確認する。 | 描画障害を Claude Code の推論や処理失敗と誤認する。 |
| Claude Code へ入力できない | Claude Code が入力待ちか、処理中か、許可待ちかを確認する。 | ターミナルがキー入力を子プロセスへ渡しているかを確認する。 | Emacs のキーマップと入力フォーカスを確認する。 | 処理中で入力を受け付けない状態を、キー設定の故障と誤認する。 |
| zellij-send.el が更新されない | Zellij の対象ペインで処理が完了しているかを確認する。 | 画面取得または完了時フックが動作したかを確認する。 | emacsclient、Emacs server、対象バッファの対応を確認する。 | 通知だけが失敗しているのに Claude Code を再起動し、完了済みの状態を失う。 |
| 会話履歴が違う | 現在の Zellij セッションと作業ディレクトリを確認する。 | 選択された Claude Code の会話記録を確認する。 | Emacs バッファとの対応付けと最終更新時刻を確認する。 | 別セッションの前提を現在の会話へ持ち込み、誤った指示を続ける。 |
| ファイル内容が食い違う | Emacs バッファに未保存変更があるかを確認する。 | ディスク上の内容と更新時刻を確認する。 | 外部 CLI が読んだ版と変更した版を差分で確認する。 | 古いバッファから保存し直し、外部プロセスの変更を上書きする。 |
障害切り分けでは、画面から最終結果が得られるかだけを試しても、失敗した層を特定できない。ローカル RAG の構築では、画面、生成 API、埋め込み処理、検索索引を一つずつ分け、隣接する層の間で入出力を確認した[10]。Emacs と AI の接続でも、入力が外部へ渡ったか、外部処理が結果を返したか、その結果が画面へ表示されたかを順に確認する必要がある。
一方向の確認が有効なのは、原因候補を減らせるからである。たとえば、Ollama API へ直接要求して回答が返れば、モデルの起動と API の処理は確認済みになる。その状態で gptel だけが失敗するなら、確認対象を Emacs 側の接続設定へ限定できる。Zellij のペインに完了表示があれば、Claude Code の実行より、画面取得や通知経路を優先して調べられる。
統合層が増えるほど、最終画面だけを見た診断の精度は下がる。各層の単体動作、隣接層との接続、最終表示を順に確認できる手段を残しておかなければ、故障時には全体を再起動する以外の復旧方法がなくなる。再起動によって一時的に直っても、故障箇所と条件が不明なままでは、同じ組み合わせで再発する。
6.3 個人設定へ追加した機能は長期保守の対象になる
Emacs の AI 統合は、一度だけ実行するインストール手順ではなく、日常的に読み込まれる設定の一部になる。パッケージの初期化、接続先の定義、キーバインド、外部コマンドの起動、通知フック、認証情報の取得方法は、Emacs を起動するたびに評価される。導入時に動いた構成でも、Emacs、パッケージ、Claude Code、Ollama、Zellij の更新によって前提が変わる。
既稿では、Emacs 設定を長期間使う個人用の基盤として捉え、安定している土台と、仕様変更を受けやすい追加機能を分離する設計を整理した[25]。AI 統合は、Emacs パッケージだけで完結せず、更新周期の異なる API、CLI、モデル、ターミナル、外部セッションを接続するため、この分離の必要性が高い。
日常の編集に必要な起動処理と、AI 機能の初期化を同じ経路へ強く結合すると、AI 側の依存関係が壊れただけで Emacs 全体の起動に影響する。存在しない関数や外部コマンドを初期化時に参照し、そのエラーで後続の設定評価が停止すると、AI と無関係な編集機能まで読み込まれない。AI 統合を任意機能として分離しなければ、追加機能の故障範囲が基盤部分へ広がる。
遅延読み込みは、AI 機能を実際に使うまで関連パッケージを初期化しないための手段になる。外部コマンドの存在確認を加えれば、Claude Code や Zellij がない端末でも Emacs の通常起動を続けられる。初期化に失敗した場合に AI 用のキーバインドやコマンドだけを無効化すれば、故障を局所化できる。これらは起動時間を短縮するためだけでなく、変化しやすい依存関係を通常の編集環境から切り離すために使う。
| 保守対象 | 変化する契機 | 強く結合した場合の影響 | 影響を限定する設計 |
|---|---|---|---|
| Emacs パッケージ | 関数名、設定変数、必須 Emacs 版、依存パッケージが変更される。 | 初期化エラーによって Emacs の起動や後続設定が停止する。 | 遅延読み込み、機能の存在確認、失敗時の局所的な無効化を行う。 |
| 外部 CLI | 起動オプション、設定ファイル、出力形式、セッション管理が変更される。 | Emacs から起動できない、画面解析やフックが動かない状態になる。 | 実行ファイルの存在確認、版の確認、起動処理の集約を行う。 |
| モデル API | 認証方法、モデル名、要求形式、提供モデルが変更される。 | 送信操作は成功して見えても、接続先で要求が拒否される。 | 接続先設定を一か所へ集約し、API 単体の確認手段を残す。 |
| ターミナル実装 | Emacs の更新、ネイティブモジュール、端末描画、キー処理が変化する。 | Claude Code は動作していても、表示や入力だけが壊れる。 | 代替ターミナルを選べる構成と、外部端末での比較手段を残す。 |
| Zellij と通知経路 | コマンド体系、画面取得、セッション識別、フックの環境が変更される。 | 外部処理は継続していても、Emacs から発見、更新、通知できなくなる。 | セッション単体の確認、手動更新、自動通知を別々に実行できるようにする。 |
| 独自の Emacs Lisp | 接続先パッケージの内部関数や返却値が変更される。 | 公式の基本機能は動作していても、独自連携だけが壊れる。 | 公開された関数を優先し、独自処理の責務と依存先を限定する。 |
設定を分離するだけでは、互換性の問題は消えない。どの版の組み合わせで動作しているかを確認できなければ、更新後の故障を再現できない。Emacs、主要パッケージ、Claude Code、Zellij、Ollama など、処理経路へ入る構成要素について、少なくとも故障時に版を取得できる状態が必要になる。すべてを固定する必要はないが、更新前後で何が変わったかを確認できなければ、原因を推測するしかなくなる。
独自のキーバインドや補助関数にも保守費用がある。導入時には一操作を短縮する小さな関数でも、接続先パッケージの内部構造へ依存していれば、更新ごとに追従が必要になる。公式に公開された操作だけを組み合わせる場合と、内部変数や非公開関数へ直接依存する場合では、壊れやすさが異なる。自由な改造が可能であることと、その改造が将来も互換性を保つことは別である。
Emacs の AI 統合を保守する主体は、単一の製品提供者ではない。gptel は Emacs と各接続先 API の間を扱い、claude-code.el は Emacs と Claude Code の間を扱い、zellij-send.el はさらに Zellij と通知経路を結ぶ。それぞれの構成要素が個別に正常でも、接続部分が現在の版の組み合わせに適合しなければ全体は動作しない。
統合によって日々の操作が短くなるほど、その操作を成立させる設定は日常の編集環境へ深く入る。長期的に使うには、AI 機能を Emacs 全体の前提へせず、壊れたときにどの層だけを止められるか、単体でどこまで確認できるか、更新前後の差をどこで追えるかを設計しておく必要がある。Emacs の自由度は、接続方式を細かく選べる利点であると同時に、選んだ接続を維持する責任が利用者側へ残ることを意味する。
7. Emacs は AI の操作盤になっても権限境界にはならない
7.1 会話とツール実行では影響範囲が異なる
gptel を会話に限って使う場合、処理は入力内容をモデルへ送り、返答をバッファへ挿入する範囲に収まりやすい。モデルが誤った回答を返しても、その時点で直接変化するのは会話バッファや挿入先の文章である。利用者が回答を採用せず、バッファを保存しなければ、外部のファイルやコマンドへ作用しない構成を保てる。
書き換え機能を使うと、影響範囲は対話から編集対象へ移る。モデルが選択範囲に対する変更案を生成し、gptel がその結果を Emacs のバッファへ適用する。差分確認や Undo を利用できても、変更の実体は通常の編集操作と同じく Emacs のバッファに入り、保存すればディスク上のファイルへ反映される。
gptel にツールを登録すると、モデルは文章を返すだけでなく、ツール名と引数を選択できる。gptel はその要求を受け、登録された Emacs Lisp 関数を実行する[6]。関数がバッファを検索するだけなら作用は読み取りに近いが、ファイル保存、外部コマンドの起動、ネットワーク通信を含む関数であれば、モデルの選択が Emacs の外部へ副作用を生む。
影響範囲を決めるのは、ツールという名称ではなく、呼び出される関数の実装である。たとえば、ファイルを読む関数でも、対象パスを引数として自由に受け取る実装と、あらかじめ指定したディレクトリ内だけを読む実装では作用範囲が異なる。外部コマンドを実行する関数も、固定された検査コマンドだけを呼ぶ場合と、モデルが生成した任意の文字列をシェルへ渡す場合では、同じ「コマンド実行ツール」としてまとめられない。
Emacs 内での実行は隔離を意味しない。モデルが選んだツールと引数を、Emacs は通常の利用者権限で Emacs Lisp 関数として実行する。OS から見れば、人間が同じ関数を呼び出した場合と権限上の違いはない。
確認画面を置くだけでも、作用範囲が自動的に限定されるわけではない。承認時にツール名しか表示せず、対象パスやコマンド引数を示さなければ、利用者は実際の副作用を判断できない。承認経路には、実行主体、対象、引数、変更内容を含める必要がある。特に、モデルが生成した文字列をシェルへ渡す関数では、ツールの説明より実際に実行される文字列の確認が優先される。
会話からツール実行へ進むと、AI の出力は「読む対象」から「実行される入力」へ変わる。文章として誤っているだけなら採用しなければ止められるが、ツールの引数として誤っていれば、確認を通過した時点でファイルや外部状態へ反映される。gptel を導入した時点ではなく、どの関数を、どの権限で、どの確認経路を通してモデルに公開したかによって、実際の影響範囲が決まる。
7.2 Claude Code の許可とフックは Claude Code 側に残る
claude-code.el と zellij-send.el は、Claude Code への指示、画面表示、セッション管理を Emacs へ接続する。ファイルを読み書きし、シェルコマンドを実行し、外部へ通信する主体は Claude Code である。Emacs のバッファから指示を送っても、Claude Code がどの操作を自動許可し、どの操作で確認を求めるかは Claude Code 側の設定に従う。
この分離は、同じ Emacs 画面から操作していても、権限の設定場所が一つではないことを意味する。第 1 段階では、Emacs のパッケージが現在のファイルや選択範囲を Claude Code へ送る。第 2 段階では、Claude Code がその情報を基にツールやコマンドを選択する。第 3 段階では、Claude Code の許可規則が実行可否を決める。Emacs のキーバインドやバッファ設定を変更しても、Claude Code の許可規則そのものは変わらない。
Anthropic のセキュリティ文書でも、提案された変更とコマンドの確認、作業単位に応じた許可設定、必要に応じた隔離環境の使用が示されている[26]。Emacs は確認画面を見やすくしたり、指示を編集しやすくしたりできるが、Claude Code が実行する処理の安全性を Emacs が保証する構造ではない。
Claude Code の許可規則には適用範囲がある。利用者全体へ適用する設定、特定の作業ディレクトリで共有する設定、端末固有の設定、管理側から強制される設定が重なる場合、利用者が現在見ている一つの設定ファイルだけでは最終的な許可状態を判断できない。どの設定範囲から規則が適用されたかを確認しなければ、意図せず自動許可された操作や、反対に予期せず拒否された操作の原因を特定できない。
フックは Claude Code の処理前後に別の処理を接続する機能である。通知だけを行うフックであれば、主な副作用は通知の表示に限られる。ファイル整形、外部 API への送信、別コマンドの実行を行うフックでは、Claude Code 本体の処理が終わった後も追加の変更が発生する。画面上で Claude Code が提示した操作を確認しても、後続フックの内容まで同時に表示されるとは限らない。
| 処理地点 | 実行を決める主体 | 設定の所在 | Emacs から見える内容 | 見落とした場合の帰結 |
|---|---|---|---|---|
| 指示の送信 | 利用者と Emacs の連携パッケージが決める。 | Emacs のバッファ、キーバインド、パッケージ設定にある。 | 送信する文章、選択範囲、ファイルを確認できる。 | 意図しない対象や未保存の前提を Claude Code へ渡す。 |
| ツールとコマンドの選択 | Claude Code が会話と作業状態から選ぶ。 | Claude Code の実行プロセスと会話状態にある。 | 対話画面に提案内容や進行状況が表示される。 | 提案の目的だけを読み、実際のコマンドや対象を確認せず承認する。 |
| 許可判定 | Claude Code の許可機構が決める。 | 利用者、作業単位、端末固有、管理設定などの複数範囲にある。 | 確認要求または自動実行の結果として現れる。 | どの規則で自動許可されたか分からず、想定より広い操作が実行される。 |
| フック実行 | Claude Code のイベント処理が登録済みフックを起動する。 | Claude Code の設定ファイルとフック先のスクリプトにある。 | フックの出力が画面やログへ現れる場合がある。 | Claude Code 本体の操作だけを確認し、後続の外部処理を見落とす。 |
| OS 上の副作用 | Claude Code、シェル、フック先の外部コマンドが実行する。 | OS の利用者権限、作業ディレクトリ、隔離環境に依存する。 | 実行結果や変更後のファイルから確認する。 | Emacs 内の操作であることを理由に、OS 上の作用範囲を狭いと誤認する。 |
拒否用フックを追加しても、それだけで完全な権限境界が成立するわけではない。フックが判定できるのは、受け取ったイベントと引数の範囲である。別の表記、別のコマンド、別のツール経路で同じ副作用へ到達できる場合には、個別の文字列判定だけでは防げない。拒否条件を作る場合も、Claude Code の許可設定、OS の権限、隔離環境を置き換えるものではなく、追加の判定点として位置付ける必要がある。
通知用フックの失敗と、変更用フックの失敗も区別しなければならない。通知が失敗した場合、利用者が完了を把握できなくても、Claude Code の処理結果は残る。変更用フックが途中で失敗した場合、Claude Code 本体の変更は保存され、後処理だけが未完了になる場合がある。画面上で一つの処理に見えても、Claude Code 本体とフックは別の終了状態を持つ。
Emacs から Claude Code を操作する利点は、指示、画面、差分、セッションを普段の編集環境へ近付けられることである。許可規則とフックの副作用まで Emacs が管理するわけではない。操作画面を一つへ集めた後も、Claude Code の設定、OS の権限、フック先の処理を別々に確認する必要がある。
7.3 MCP は外部操作能力を追加する層である
gptel は付属の gptel-integrations を介して、mcp.el が公開するツールを登録できる[6]。その接続先となる mcp.el は、Emacs から MCP サーバーへ接続し、サーバーの起動と停止、公開されるツール、プロンプト、リソースを管理するクライアントである[27]。gptel 単体の会話に、外部システムを読み書きする経路を追加する構成になる。
MCP の構造では、AI アプリケーションがホストとなり、複数の MCP サーバーとの接続を管理する[28]。各サーバーは、自身が提供するツールと入力形式をホストへ通知する。モデルが操作を選び、Emacs 側のクライアントが接続先を特定し、MCP サーバーが外部システムへ処理を実行する。
MCP を追加すると、モデルが会話の外側から取得できる情報と、外部へ反映できる操作が増える。ファイル検索だけを公開するサーバーでは読み取り範囲が広がり、データベース更新や外部 API の変更操作を公開するサーバーでは、モデルの選択が外部状態へ作用する。
MCP サーバーが同じツール名を持っていても、実際の影響範囲は実装と接続先によって変わる。「検索」という名称でも、ローカル文書だけを読む場合、データベースへ問い合わせる場合、公開ウェブへ送信する場合では、扱う情報と通信経路が異なる。ツール一覧に加えて、どのサーバーが、どの認証情報で、どの接続先へ処理するかを確認する必要がある。
MCP の仕様は、利用可能なツールと呼び出し状態を利用者へ明示し、操作を拒否できる確認経路を持つことを推奨している[29]。確認画面では、ツール名だけでなく、対象、引数、接続先、読み取りか変更かを判断できる情報が必要になる。モデルが生成した引数を確認できなければ、承認は操作の具体的な内容ではなく、抽象的な名称への同意にとどまる。
| 機能段階 | 実行主体 | 入力の由来 | 主な影響範囲 | 確認すべき境界 |
|---|---|---|---|---|
| gptel の会話 | gptel と接続先 API が処理する。 | 利用者が入力した文章、選択範囲、追加文脈を使う。 | 送信した情報と、返答を挿入するバッファに及ぶ。 | 送信内容、接続先、履歴保存、回答の採用を確認する。 |
| gptel の書き換え | gptel と Emacs が処理する。 | モデルの生成結果をバッファ変更として使う。 | 選択範囲、対象バッファ、保存後のファイルに及ぶ。 | 差分、Undo、保存前の内容を確認する。 |
| gptel の Emacs Lisp ツール | 登録された Emacs Lisp 関数が処理する。 | モデルが選んだツール名と引数を使う。 | 関数がアクセスできるバッファ、ファイル、外部コマンドに及ぶ。 | 関数実装、対象範囲、引数、承認方法を確認する。 |
| Claude Code | Claude Code CLI と呼び出された外部コマンドが処理する。 | 会話、作業ファイル、Claude Code の判断を使う。 | 許可されたファイル操作、コマンド、ネットワーク利用に及ぶ。 | 許可設定、作業ディレクトリ、コマンド、フック、隔離環境を確認する。 |
| MCP ツール | MCP サーバーと接続先の外部システムが処理する。 | モデルが選んだツールと引数をホストがサーバーへ渡す。 | サーバーが公開するデータ、ファイル、データベース、外部 API に及ぶ。 | サーバー実装、公開ツール、認証、接続先、読み取りと変更の区別を確認する。 |
MCP では、Emacs、MCP クライアント、MCP サーバー、外部サービスが別の権限を持つ。Emacs が接続設定を保持していても、外部サービスへの認証は MCP サーバー側で行われる場合がある。サーバーを停止すれば接続を切れるが、既に外部サービスへ反映された変更までは取り消されない。接続の有効化、操作の実行、外部状態の変更は別の処理である。
Emacs は、会話、書き換え、Claude Code、MCP を同じ操作環境へ集められる。その一体感は、異なる実行主体への入口が一つの画面に並んだ結果であり、権限が統合された結果ではない。同じ Emacs 画面を使っていても、会話だけの構成、Emacs Lisp ツールを有効にした構成、Claude Code を動かす構成、MCP サーバーを接続した構成では到達できる範囲が異なる。
Emacs が表示し、利用者が承認する地点は操作上の検査点になる。実際の権限境界は、Emacs プロセス、Claude Code、MCP サーバー、OS、外部サービスがそれぞれ持つ許可と隔離によって決まる。操作を一つへ集約しても、実行主体ごとの権限確認は残る。
8. 方式は Emacs に取り込みたい作業で選ぶ
8.1 三方式は置き換え関係ではない
gptel、claude-code.el、zellij-send.el は、同じ AI 機能を異なる画面で提供する代替品ではない。各方式が Emacs へ取り込む処理の範囲が異なる。gptel は、モデルへの要求と回答を通常バッファへ統合する。claude-code.el は、Claude Code が持つ対話状態をターミナル画面ごと Emacs 内へ置く。zellij-send.el は、指示の作成と履歴の閲覧を通常バッファへ移し、実行中の対話状態は Zellij の外部セッションへ残す。
同じ質問を三方式から送れる場合でも、質問後の工程は一致しない。gptel では、回答を通常の文章として編集し、書き換え結果を差分として確認しやすい。claude-code.el では、Claude Code が提示する許可確認や選択肢へ、その対話状態を保ったまま応答できる。zellij-send.el では、Claude Code の処理中に別のバッファへ移り、複数の外部セッションを並行して監視できる。方式選択は、送信できるかどうかではなく、送信後にどの操作を続けたいかで決まる。
三方式を併用する構成も成立する。局所的な質問や文章の書き換えには gptel を使い、Claude Code の対話操作が必要な処理だけを claude-code.el または zellij-send.el へ渡せる。ただし、併用すると、会話履歴、対象ファイル、モデル設定、実行セッションが複数の仕組みへ分かれる。同じ対象について別方式で質問を続けても、一方の会話履歴や追加文脈が他方へ自動的に引き継がれるわけではない。
| 重視する作業 | 適合しやすい方式 | 得られる操作 | 受け入れる管理 | 選択が合わない条件 |
|---|---|---|---|---|
| 選択範囲への質問と書き換え | gptel | 通常バッファから対象を指定し、回答や変更候補を差分として扱える。 | モデルごとの接続設定、追加文脈、実際の送信内容を管理する。 | Claude Code 固有の許可確認や対話状態をそのまま操作する必要がある場合には不足する。 |
| 会話を Org や Markdown として保存 | gptel | 会話を通常文書として編集、検索、保存、再利用できる。 | 編集後の文書と実際の対話履歴、モデル設定、追加文脈を区別する。 | 端末画面上の進行状態や一時的な確認要求を完全に再現したい場合には適さない。 |
| Claude Code の対話画面を直接操作 | claude-code.el | 許可確認、選択肢、進行表示、対話コマンドをターミナル内で扱える。 | ターミナル実装、キー転送、画面幅、スクロールバックを調整する。 | Emacs の入力メソッドと通常編集を対話欄で常時使いたい場合には摩擦が大きい。 |
| 通常バッファで長い指示を編集 | zellij-send.el | 入力メソッド、検索、置換、Undo を使って指示を完成させてから外部画面へ送れる。 | 入力バッファ、現在画面、会話記録を別の状態として管理する。 | 対話画面の候補選択や許可確認を頻繁に直接操作する場合には手数が増える。 |
| 長時間処理を Emacs から切り離す | zellij-send.el | Zellij の切り離されたセッションで処理を継続し、後から再接続できる。 | セッション名、ペイン ID、作業ディレクトリ、通知、履歴を対応付ける。 | 一つの短い処理だけをその場で確認する用途では構成が過剰になる。 |
| ローカルモデルとクラウドモデルを同じ編集操作で切り替える | gptel | 接続先を変更しても、リージョン、バッファ、書き換えの操作を維持できる。 | モデル能力、文脈長、速度、端末資源、外部送信の有無を接続先ごとに評価する。 | 接続先を切り替えれば同じ品質と動作が得られると期待する場合には判断を誤る。 |
| 外部ツールをモデルから呼び出す | gptel と MCP、または Claude Code | 会話からファイル、コマンド、外部サービスの操作へ進める。 | 実行主体、引数、許可設定、接続先、変更後の副作用を確認する。 | 回答を読むだけの用途に対しては、権限と保守対象を不必要に増やす。 |
選択表は、各方式を一つだけ採用するための順位ではない。日常的に繰り返す作業を最も短い経路へ置き、使用頻度の低い操作は独立した画面へ残すための判断材料である。文章の書き換えを毎日行い、Claude Code の長時間処理をまれにしか使わないなら、gptel を常設し、Claude Code は必要時だけ独立したターミナルで起動する構成も合理的である。
8.2 統合しない方が短い作業もある
Emacs 統合には、導入後も継続する固定費がある。パッケージの更新、認証情報の管理、モデル名の変更、キーバインドの競合、外部 CLI の更新、障害時の切り分けは、AI を使用していない時間にも保守対象として残る。単発の質問で一度だけコピーと貼り付けを行う場合、その操作を削減するために長期間の設定保守を追加しても、作業全体は短くならない。
統合によって削減できる操作は、利用するたびに発生する変動費に当たる。編集対象のコピー、質問画面への移動、回答の転記、対象箇所の再検索を一回ごとに省ける。これに対して、パッケージ導入、初期設定、更新追従、障害対応は固定費として発生する。同じ操作を繰り返す回数が増えるほど、統合による短縮が固定費を上回りやすくなる。
| 利用条件 | 統合によって減る操作 | 追加される固定費 | 判断 |
|---|---|---|---|
| 月に数回の単発質問 | 画面移動と短いコピー操作が数回減る。 | 接続設定、認証、更新追従、キーバインド管理が残る。 | ブラウザーや独立した端末の方が全体の管理量を抑えやすい。 |
| 同じバッファで繰り返す文章推敲 | 選択、送信、差分確認、反映までの往復が毎回減る。 | gptel と利用する接続先の保守が必要になる。 | 利用回数が多ければ、通常バッファへの統合効果を回収しやすい。 |
| Claude Code を短時間だけ利用 | Emacs から起動し、現在のファイルを送る操作を短縮できる。 | ターミナル実装と claude-code.el の保守が増える。 | 独立したターミナルでの利用に不都合がなければ、統合の必要性は低い。 |
| 複数の長時間処理を並行 | 処理ごとの端末移動、再接続、状態確認を一覧化できる。 | Zellij、セッション識別、通知、履歴再構成を管理する。 | 並行処理の頻度が高い場合には、外部セッション管理の固定費を回収しやすい。 |
| 複数モデルの継続的な使い分け | モデルごとに別の画面や操作を覚える必要が減る。 | 接続先ごとの設定、能力差、入力制限を管理する。 | 操作の共通化に価値はあるが、モデル差まで消えるわけではない。 |
統合しない選択は、AI を活用しないことを意味しない。AI の利用経路を Emacs の外へ残し、必要なときだけ独立したブラウザーやターミナルを開く構成である。処理と状態が一つの外部画面にまとまるため、Emacs の起動設定や通常操作へ影響を与えにくい。使用頻度が低い機能ほど、独立した経路へ残す利点が大きくなる。
反対に、同じ編集対象へ繰り返し質問し、生成結果を差分で確認し、会話を文書として保存する場合には、対象のコピー、回答の転記、変更箇所の再検索が毎回発生する。この反復が日常の編集工程へ組み込まれているなら、通常バッファから直接操作できる価値は一回の短縮量ではなく、累積した操作量として現れる。
8.3 操作距離の短縮と状態管理の増加を同時に評価する
Emacs と AI を接続すると、指示、編集対象、回答、差分、履歴を普段の編集環境へ近付けられる。リージョンを選び、同じバッファから要求を送り、回答を通常の文章として受け取り、Undo や Ediff で変更を確認できる。gptel の接続先を変更すれば、ローカルの Ollama とクラウド API を同じ編集操作の背後へ置ける。
この操作距離の短縮は、複数の状態が一つへ統合された結果ではない。Emacs が対象範囲と入力文を保持して外部のモデルまたはエージェントへ送り、外部処理が回答やファイル変更を生成し、その結果を Emacs が表示する経路を接続した結果である。gptel の要求内容、接続先 API、Claude Code の許可状態、ターミナルの現在画面、Zellij のセッション、会話記録、Emacs server、フック、MCP サーバーは別々に動作する。接続を増やすほど、どこで失敗したかを判定するための状態管理も増える。
方式の選択では、どの画面で対象を選び、どこで指示を書き、どこで進行状態を見て、どこで結果を比較し、どこへ履歴を残しているかを分解する。その中で繰り返し発生し、取り違えや転記漏れが起きやすい部分だけを Emacs へ移す。回答を通常の編集対象として扱うなら gptel、Claude Code の対話状態を保つなら claude-code.el、通常バッファの入力と外部での処理継続を両立させるなら zellij-send.el が適する。
Emacs と AI の接続によって得られる利点は、編集対象を選び、指示を整え、生成結果を比較し、採用または撤回する工程を普段の編集操作へ接続できることである。必要な作業だけを取り込めば、Emacs の編集性を利用しながら、外部プロセス、履歴、権限、通知の分散を限定できる。
参考文献
- Free Software Foundation, Using Multiple Buffers, GNU Emacs Manual. https://www.gnu.org/software/emacs/manual/html_node/emacs/Buffers.html
- karthink, gptel: A simple, extensible LLM client for Emacs. https://github.com/karthink/gptel
- Steve Molitor, claude-code.el: Claude Code Emacs integration. https://github.com/stevemolitor/claude-code.el
- Anthropic, Overview, Claude Code Docs. https://code.claude.com/docs/en/overview
- ichibeikatura, zellij-send.el: Chat with Claude Code and other AI agents in zellij, from Emacs. https://github.com/ichibeikatura/zellij-send.el
- karthink, gptel Manual. https://gptel.org/manual.html
- Free Software Foundation, Input Methods, GNU Emacs Manual. https://www.gnu.org/software/emacs/manual/html_node/emacs/Input-Methods.html
- Ollama, Introduction, API Reference. https://docs.ollama.com/api/introduction
- id774, MacBook Pro でローカル LLM を実用化する条件(2026-07-17). https://blog.id774.net/entry/2026/07/17/5102/
- id774, MacBook Pro にローカル RAG を構築する(2026-07-18). https://blog.id774.net/entry/2026/07/18/5104/
- Free Software Foundation, Undoing Changes, GNU Emacs Manual. https://www.gnu.org/software/emacs/manual/html_node/emacs/Basic-Undo.html
- Free Software Foundation, Ediff User’s Manual. https://www.gnu.org/software/emacs/manual/html_node/ediff/
- Free Software Foundation, Compilation, GNU Emacs Manual. https://www.gnu.org/software/emacs/manual/html_node/emacs/Compilation.html
- Free Software Foundation, Auto Revert: Keeping buffers automatically up-to-date, GNU Emacs Manual. https://www.gnu.org/software/emacs/manual/html_node/emacs/Auto-Revert.html
- Anthropic, Configure your terminal for Claude Code. https://code.claude.com/docs/en/terminal-config
- Zellij, Programmatic Control, Zellij User Guide. https://zellij.dev/documentation/programmatic-control.html
- Free Software Foundation, Processes, GNU Emacs Lisp Reference Manual. https://www.gnu.org/software/emacs/manual/html_node/elisp/Processes.html
- Free Software Foundation, Creating an Asynchronous Process, GNU Emacs Lisp Reference Manual. https://www.gnu.org/software/emacs/manual/html_node/elisp/Asynchronous-Processes.html
- Zellij, CLI Recipes & Scripting, Zellij User Guide. https://zellij.dev/documentation/cli-recipes.html
- Zellij, Session Resurrection, Zellij User Guide. https://zellij.dev/documentation/session-resurrection.html
- Free Software Foundation, Emacs Server, GNU Emacs Manual. https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html
- Free Software Foundation, Invoking emacsclient, GNU Emacs Manual. https://www.gnu.org/software/emacs/manual/html_node/emacs/Invoking-emacsclient.html
- Anthropic, Claude Code settings. https://code.claude.com/docs/en/settings
- Anthropic, Automate actions with hooks, Claude Code Docs. https://code.claude.com/docs/en/hooks-guide
- id774, Emacs Lisp の実装ガイドラインを改訂した(2026-03-17). https://blog.id774.net/entry/2026/03/17/4042/
- Anthropic, Security, Claude Code Docs. https://code.claude.com/docs/en/security
- lizqwerscott, MCP.el – Model Context Protocol for Emacs. https://github.com/lizqwerscott/mcp.el
- Model Context Protocol, Architecture overview(2026-07-28). https://modelcontextprotocol.io/docs/2026-07-28/learn/architecture
- Model Context Protocol, Tools(2026-07-28). https://modelcontextprotocol.io/specification/2026-07-28/server/tools