AIコーディングエージェントがサーバーで何を実行しているかを見る方法

エージェントが本番サーバーで作業していて、ターミナルには「ツールを呼び出しています」としか出ていません。実際にどのコマンドを実行し、マシンは何を返したのか。トランスクリプトを読めば後からは分かります。それを実行中に見えるようにした方法、最初に試して失敗したこと、そして私たちのアプリを使わずに同じことを実現する方法を紹介します。

DevOps エージェントに、本番 API が遅い理由を聞いたとします。エージェントが作業を始めます。ターミナルには「ツールを呼び出しています」という行が一つ、また一つ、さらにもう一つ。六回の呼び出しのあと、ディスクが 97 % 埋まっていると伝え、ログのディレクトリを掃除しましょうかと提案してきます。

そのマシンで実際に何を実行したのでしょうか。どんな du を、どんな find を打ったのか。もう何か消してしまったのか。答えは存在します。ただしそれはセッションのトランスクリプトの中に JSON で書かれていて、読むのは事が済んだあとです。ノートパソコンならそれで構いません。本番サーバーでは、事が済んでからでは「待って、そのフォルダじゃない」と言うには遅すぎます。

私たちが作っている AgentsRoom は、コーディングエージェントを動かし、サーバー、データベース、クラスターに届くツールを渡すデスクトップアプリです。これは、そうした呼び出しを実行中に見えるようにした経緯の記録です。うまくいかなかった版、うまくいった版を支える数字、そして私たちのアプリを使わずに同じことを実現する方法をまとめます。

短い答え

  • CLI が見せるのはツールが動いたという事実で、向こう側のセッションではありません。 完全なコマンドとその出力は、ディスク上のトランスクリプトに書かれます。
  • ライブで見るには、各呼び出しを開始した時点で記録する何かが必要です。 セッションが終わった時点では遅いのです。
  • 接続ごとに一つのログはうまくいきます。コマンドごとに一つのターミナルタブはうまくいきません。 一つのセッションで 166 件のリモートコマンドを計測しました。
  • そのログは自分のマシンに置いておくこと。 本番ホストのコマンドラインには、シークレットも顧客データも含まれます。
  • 私たちのアプリなしでも: シェルコマンドをすべてファイルに追記する Claude Code の hook で大部分はまかなえ、残りはトランスクリプトが補ってくれます。

サーバーではトランスクリプトだけでは足りない理由

Claude Code も Codex もほかの CLI も、すべてをきちんと記録しています。Claude Code は ~/.claude/projects/ の下にセッションごとに JSONL ファイルを一つ、Codex は ~/.codex/sessions/ の下に一つ書きます。ツールの呼び出しはすべて、入力と結果とともにそこに入っています。

問題は網羅性ではなく、タイミングと形です。トランスクリプトは CLI がセッションを再開するために書かれています。読むのはエージェントが止まってからで、JSON の行を掘り返すことになります。三つのエージェントが同時に動けば、三つのファイルを読むことになります。そして実際に目を向けている場所であるエージェントのターミナルには、各呼び出しの折りたたまれた要約しか出ません。

ノートパソコン上のコードなら、後から読み返すのが普通のレビューの流れです。コミットする前に diff を見ればいい。サーバーには diff がありません。systemctl restart も DELETE も、実行した瞬間に効いてしまいます。

最初に試したこと、そして 166 件のコマンド

エージェント向けの最初のリモートツールは、ターミナルタブの中で接続を開くものでした。正しく見えました。ユーザーはセッションを見られるからです。ところが、予想しなかった形で失敗しました。

このツールには、開いたばかりのタブで何が起きたかをエージェントが読み取る手段がありませんでした。そのため、あるユーザーのプロジェクトで、エージェントはこのツールを使うのをやめてしまいました。そのセッションの集計は、私たちの接続ツールの呼び出しが 16 件、エージェント自身のシェルツールで実行された sshpass コマンドが 166 件。エージェントはユーザーにパスワードを尋ね、ユーザーはそれをチャットに貼り付けていました。本番の認証情報は、トランスクリプトに平文で、各コマンドの実行中は ps aux に、さらに /tmp の下のファイルに残ることになりました。

教訓は「エージェントは無謀だ」ではありませんでした。エージェントは、うまくいく唯一の方法を取っただけです。安全でもエージェントに仕事をさせないツールは迂回され、その迂回はツールがないよりも悪い結果になります。

そこで ssh_exec を作りました。エージェントはコマンドを一つ送り、AgentsRoom がパスワードをアプリ内に保ったまま保存済みの接続でそれを実行し、出力と終了コードを返します。エージェントは認証情報を一度も見ず、sshpass の行を組み立てる理由もなくなります。

これでセキュリティの問題は解決し、代わりに見えにくさの問題が生まれました。ssh_exec のたびにタブを開いていたら、あのセッションでは 166 個のタブができていたはずです。だから ssh_exec はタブを一つも開かず、二か月のあいだ、それらのコマンドを見られる場所はまたしてもエージェントの会話だけでした。

接続ごとに一つのログ

2026年10月29日にリリースした版(AgentsRoom 1.242.0)は、一つのルールを守っています。コマンドごとのタブは作らない。その代わり、すべての呼び出しが接続ごとに一つのログに入ります。

  • 右パネルのアクティビティタブは、ファイル、変更、テストの隣にあります。エージェントが触れた接続をカード(最後のコマンド、エージェント、時刻、状態)で並べ、直近 40 件の呼び出しをタイムラインに表示します。エージェントで絞り込め、コマンド、接続名、出力を検索できます。
  • 接続のログはターミナルのように読めます。エージェント · 時刻、次に $ コマンド、次に出力、最後に 完了 · 終了コード 0 · 1.2 s。SSH の出力はライブで流れ、上にスクロールしない限り表示は末尾を追い続けます。ボタン一つでログ全体をテキストとしてコピーできます。
  • エージェントのヘッダーにあるピルは、そのエージェントが触れたサーバー、データベース、クラスターごとに一つずつあり、呼び出し中は緑の点が付きます。クリックするとそのログが開きます。
  • 「エージェント作業中」バッジは、サーバー、データベース、Kubernetes の各ウィンドウで接続の行に付き、呼び出しの実行中だけ表示されます。

ログは読み取り専用です。自分でマシンに入力したいときは、これまでどおりサーバーウィンドウの SSH タブを使います。機能の詳しいページは AIエージェントのための SSH 接続 で、データベース側は データベース接続 にあります。

記録されるもの、されないもの

呼び出しログに入るか理由
ssh_exec(SSH、AWS SSM、WinRM)はい本命のケース。リモートマシン上のコマンドで、専用のタブを持たない
ssh_transferはいサーバーとのあいだのファイルコピーは、そのサーバーに対する操作
db_query、db_schemaはいエージェントが書いたとおりの SQL と、結果の先頭の数行
kube_kubectlはい引数付きの kubectl の行として表示
commands_run、ssh_connectいいえすでに見ていられるターミナルタブを開く
エージェント自身のシェルツール(直接打った ssh、psql、kubectl)いいえAgentsRoom を通らない。エージェントのターミナルとトランスクリプトに残る

最後の行が、正直な限界です。ログに見えるのは私たちのツールを通ったものだけです。すべてのリモート操作をそこに出したいなら、エージェントにとってツールのほうが楽な道でなければなりません。それが 166 件のコマンドの教訓です。

もう一つ細かい点があります。コマンドの実行中に出力が流れるのは SSH だけです。手元のマシンの本物のターミナルを通るからです。WinRM、SQL、kubectl の結果は、呼び出しが終わった時点で表示されます。

ログを持ち続けるコスト

私たちのユーザーは大量のエージェントを同時に動かしています。あるマシンでは 18 プロジェクトにまたがる 45 エージェント、別のマシンでは 48 のコンソール。エージェントごと、出力のかたまりごとに数えるものはすべてこの数で掛け算になるので、ログには厳しい上限を設けています。

  • プロジェクトごとに 120 件の呼び出し。古いものから捨てます。
  • 呼び出しごとに出力 32,000 文字。残すのは末尾で、エラーや終了コードがあるのはそこだからです。
  • 呼び出しごとにコマンドまたは SQL は 2,000 文字。
  • ライブ出力の更新メッセージは呼び出しごとに 120 ms に一回。ターミナル出力のかたまりごとに一回ではありません。
  • 待機中はタイマーなし。 どのエージェントもリモートツールを呼んでいないあいだ、ログのコストはゼロです。

記録は一か所で行います。すべての CLI のツール呼び出しが通るブリッジです。だから Claude Code でも Codex でも Antigravity CLI でも、アプリが動かすほかのどの CLI でも、プロバイダーごとのコードなしに同じように動きます。

選んだ制限:何もマシンの外に出さない

ログはデスクトップアプリのメモリに保持され、アプリを終了すると消えます。私たちのサーバーには同期されません。これは私たちとしては珍しいことです。AgentsRoom のほとんどのものは、アカウントに紐づいてコンピューターをまたいでついてくるからです。

これだけは違います。意図的にです。サーバーで実行した env の出力にはシークレットが含まれます。顧客テーブルへの SELECT には顧客データが含まれます。それらを見えるようにするためのツールが、ついでにどこか新しい場所へコピーしてしまうべきではありません。

スマートフォンからも、エージェントのプロフィールで同じログを追えます(モバイルアプリ 2.47 以降)。ストリームはエンドツーエンド暗号化された接続を通ってコンピューターからスマートフォンへ届き、シークレットは送り出す前にマスクされ(API キー、KEY=value の組、URL 内のパスワード、トークン)、サーバーには何も保存されません。同じ呼び出しは、これまでどおりエージェントの会話でも読めます。

Claude Code の監査ログは別物

「Claude Code 監査ログ」で検索したなら、おそらく Claude Enterprise 向けの Anthropic の Compliance API に行き着いたはずです。アクティビティフィード、監査ログのイベント、そして Enterprise アカウントにサインインしたローカルセッションならセッションのトランスクリプト。管理者やコンプライアンスチームのために作られていて、対象は組織全体、読むのは事後です。

これが答えるのは「社内の誰が Claude で何をしたか」です。「いまこの瞬間、エージェントがデータベースサーバーでどのコマンドを実行しているか」には答えません。二つは共存できますし、コンプライアンス要件のある会社で働いているなら、後者に何を使うかに関係なく、前者はおそらく必要です。

AgentsRoom を使わない場合

CLI がすでに提供しているもので、その大部分は手に入ります。

シェルコマンドを開始した時点ですべて記録する。 Claude Code の hook は、ツールの呼び出しの前にコマンドを実行できます。hook のガイドにそのパターンが載っています。Bash ツールに対する PreToolUse hook で、jq -r .tool_input.command の結果をログファイルに流し込むものです。別のターミナルでそのファイルに tail -f をかければ、エージェントが送った瞬間に各コマンドが見えます。ssh の行も含めてです。

出力が必要なときはトランスクリプトを読む。 hook で分かるのはコマンドで、サーバーが何を返したかではありません。そちらは ~/.claude/projects/ の下のセッションファイル(Codex なら ~/.codex/sessions/)に、すべての呼び出しの完全な結果が入っています。

サーバー上にエージェント専用のアカウントを用意する。 専用ユーザーにすれば、すべての接続がサーバーの認証ログで誰のものか分かります。サーバーで auditd が動いているなら、そのユーザーの execve に対するルールで、起動したプロセスを一つ残らずサーバー側で記録できます。エージェントには飛ばせない場所です。

認証情報をエージェントの手の届かないところに置く。 接続する唯一の手段が、エージェントがあなたに尋ねるしかないパスワードなら、チャットに sshpass の行が現れることになります。エージェントが決して読まない鍵を使うか、代わりにシークレットを預かるツールを使いましょう。プロンプトに書かずにエージェントへシークレットを渡す方法は別の記事にまとめています。

この構成で得られないのは、三つのつながりです。どのエージェントが、どの接続で、どんなライブ出力を出しているかを、一か所で見ること。それが私たちの作った部分です。

実際によく聞かれる質問

Claude Code がリモートサーバーで何をしているか、作業中に見ることはできますか?

ターミナルに表示されるのは、ツールの呼び出しと、終わったあとの短い結果だけです。完全なコマンドとその出力はディスク上のセッションのトランスクリプトに書き込まれ、それを読むのは後になります。実行中に見るには、各呼び出しを開始した時点で記録する仕組みが必要です。Bash のコマンドをすべてログファイルに書き出す Claude Code の hook か、エージェントの代わりにリモートの呼び出しを実行してライブで表示するアプリです。後者が AgentsRoom のアクティビティタブです。

Claude Code は実行したコマンドの記録をどこに残していますか?

セッションのトランスクリプトです。~/.claude/projects/ の下にある JSONL ファイルで、プロジェクトごとに一つのフォルダ、セッションごとに一つのファイルです。ツールの呼び出しは一つずつ、入力と結果を含む一行になっています。Codex も ~/.codex/sessions/ の下にセッションごとの同様のファイルを持っています。どちらも完全ですが、どちらも CLI がセッションを再開するためのもので、人が目で追うためのものではありません。

これは Claude Code の監査ログと同じものですか?

違います。その名前で探される監査ログとは、Anthropic が Enterprise プランで Compliance API を通じて提供している組織単位の記録です。アクティビティフィード、監査イベント、そしてサインイン済みのセッションならトランスクリプトがあり、管理者が後から読みます。答えるのは「組織の中で誰が何をしたか」です。一台のサーバー上のコマンドをライブで見る画面は、別の人のための別のツールです。

エージェントが実行するコマンドごとにターミナルタブを開けばよいのでは?

その道は実際に試し、計測もしました。本番の障害に対応していたエージェントは、一つのセッションで 166 件のリモートコマンドを実行しました。コマンドごとにタブを開くと、十分もすればタブバーは使い物になりません。うまくいくのは接続ごとに一つのログで、各呼び出しがコマンド、ライブの出力、終了コード、所要時間を持つ一つのエントリーになる形です。

AgentsRoom はコマンドとその出力をサーバーに送っていますか?

いいえ。ログはデスクトップアプリのメモリ上にあり、プロジェクトごとに 120 件の呼び出しが上限で、アプリを終了すると消えます。スマートフォンからはエージェントのプロフィールで追えます(モバイルアプリ 2.47 以降)。ストリームはエンドツーエンド暗号化された接続を通ってコンピューターからスマートフォンへ直接届き、シークレットはマスクされ、サーバーには何も保存されません。

アクティビティタブに表示されないエージェントのコマンドはどれですか?

記録されるのは AgentsRoom のツールを通る呼び出しだけです。ssh_exec、ssh_transfer、db_query、db_schema、kube_kubectl です。エージェントが自分のシェルツールで実行したコマンド、たとえば直接打った ssh や psql の行は、そのターミナルとトランスクリプトには残りますが、ログには入りません。commands_run と ssh_connect は意図的に対象外です。どちらもすでに、見ていられるターミナルタブを開くからです。

まとめ

サーバーで動くエージェントには、あなたから二つのものが必要です。あなたのパスワードを介さずに作業できる手段と、エージェントが作業している最中にそれを見られる手段です。前者だけで後者がなければ、事後に JSON を読むことになります。後者だけで前者がなければ、sshpass の行を貼り付けるエージェントに迂回されます。

私たちがたどり着いたのは、接続ごとに一つの、上限付きで、自分のマシンに置かれるログでした。試してみたいなら AgentsRoom は無料でダウンロードでき、SSH 接続のページで設定を順を追って説明しています。CLI だけで続けたいなら、まずは PreToolUse hook と tail -f から始めてください。五分で済みますし、直近六回のツール呼び出しが何だったのかと悩むことは二度となくなります。

AgentsRoomをダウンロード

すべてのAIエージェントを、すべてのプロジェクトで、ひとつのウィンドウから実行。

無料AgentsRoomをダウンロード

コンパニオンアプリ:外出先でもエージェントを確認

Claude、Codex、Antigravity CLI、またはその他の AI プロバイダーを使用します。

拡張機能を入手
Chrome Web Store

バグや要望を公開バックログに直接送信できます。

マルチプロジェクト
マルチプロバイダー
マルチエージェント
ライブステータス
ファイル差分
モバイルアプリ
ライブプレビュー
エージェントチーム
ブラウザテスト
バックログ駆動開発
プロンプトライブラリ
スキルライブラリ
すべての機能を見る

続きを読む