How to See What Your AI Coding Agent Runs on Your Servers
Your agent is on a production server and the terminal only says it is calling a tool. Which command did it run, and what did the machine answer? The transcript tells you afterwards. Here is how we made it visible while it happens, what we tried first, and how to get the same thing without our app.
You ask a DevOps agent why the production API is slow. It starts working. In its terminal you see a line saying it is calling a tool, then another, then another. Six calls later it tells you the disk is 97 % full and offers to clean the log directory.
What did it actually run on that machine? Which du, which find, did it already delete something? The answer exists, but it is in the session transcript, written as JSON, and you read it after the fact. On a laptop that is fine. On a production server, after the fact is too late to say "wait, not that folder".
We build AgentsRoom, a desktop app that runs coding agents and gives them tools to reach your servers, databases and clusters. This is the story of how we made those calls visible while they happen, the version that did not work, the numbers behind the one that does, and how to get the same thing if you do not use our app.
The short answer
- The CLI shows you that a tool ran, not the session on the other side. The full command and its output go to the transcript on your disk.
- To watch it live, something has to record each call when it starts, not when the session ends.
- One journal per connection works. One terminal tab per command does not. We measured 166 remote commands in a single session.
- Keep that journal on your machine. A command line on a production host carries secrets and customer data.
- Without our app: a Claude Code hook that appends every shell command to a file gets you most of the way, and the transcript gives you the rest.
Why the transcript is not enough on a server
Claude Code, Codex and the other CLIs do record everything. Claude Code writes one JSONL file per session under ~/.claude/projects/, Codex one under ~/.codex/sessions/. Every tool call is in there with its input and its result.
The problem is not completeness, it is timing and shape. The transcript is written for the CLI, so it can resume a session. You read it once the agent has stopped, by digging through lines of JSON. When three agents work at once, you read three files. And the terminal of the agent, the place you are actually looking, only shows a folded summary of each call.
For code on your laptop, reading afterwards is the normal review loop: you look at the diff before you commit. A server has no diff. A systemctl restart or a DELETE takes effect the moment it runs.
What we tried first, and the 166 commands
Our first remote tool for agents opened a connection in a terminal tab. That looked right: the user could see the session. It failed in a way we did not expect.
The tool gave the agent no way to read what happened in the tab it had just opened. So on one user's project, the agent stopped using it. The count in that session: 16 calls to our connection tool, and 166 sshpass commands run through the agent's own shell tool, with the agent asking the user for the password and the user pasting it into the chat. Production credentials ended up in plain text in the transcripts, in ps aux while each command ran, and in a file under /tmp.
The lesson was not "agents are reckless". The agent did the only thing that worked. A safe tool that does not let the agent do its job gets bypassed, and the bypass is worse than having no tool.
So we wrote ssh_exec: the agent sends one command, AgentsRoom runs it on the saved connection with the password kept in the app, and returns the output and the exit code. The agent never sees the credential and has no reason to build an sshpass line.
That fixed the security problem and created a visibility one. If each ssh_exec opened a tab, that session would have produced 166 tabs. So ssh_exec opened none, and for two months the only place to see those commands was, again, the agent's conversation.
One journal per connection
The version we shipped on 29 October 2026 (AgentsRoom 1.242.0) keeps one rule: no tab per command. Instead, every call lands in a journal, one per connection.
- The Activity tab of the right panel, next to Files, Changes and Tests, lists the connections agents touched as cards (last command, agent, time, state) and the 40 most recent calls on a timeline. It filters by agent and searches commands, connection names and output.
- The journal of a connection reads like a terminal:
agent · time, then$ command, then the output, thenDone · exit 0 · 1.2 s. SSH output scrolls in live and the view follows the bottom until you scroll up. A button copies the whole journal as text. - Pills in the agent's header, one per server, database or cluster that agent touched, with a green dot during a call. One click opens that journal.
- An Agent at work badge on the connection's row in the Servers, Databases and Kubernetes windows, only while a call runs.
The journal is read-only. To type into the machine yourself, the SSH tab of the Servers window is still the way in. The full feature page is SSH connections for AI agents, and the database side is on database connections.
What is recorded, and what is not
| Call | In the journal | Why |
|---|---|---|
ssh_exec (SSH, AWS SSM, WinRM) | Yes | The main case: a command on a remote machine, with no tab of its own |
ssh_transfer | Yes | A file copied to or from a server is an action on that server |
db_query, db_schema | Yes | The SQL as the agent wrote it, and the first rows of the result |
kube_kubectl | Yes | Shown as the kubectl line with its arguments |
commands_run, ssh_connect | No | They already open a terminal tab you can watch |
The agent's own shell tool (ssh, psql, kubectl typed directly) | No | It does not go through AgentsRoom: it is in the agent's terminal and transcript |
The last line is the honest limit. The journal sees what goes through our tools. If you want every remote action to show up there, the tools have to be the easier path for the agent, which is the lesson of the 166 commands.
One more detail: only SSH streams output while the command runs, because it goes through a real terminal on your machine. WinRM, SQL and kubectl results appear when the call finishes.
What it costs to keep the journal
Our users run a lot of agents at once: 45 agents across 18 projects on one machine, 48 consoles on another. Anything counted per agent or per output chunk gets multiplied by that, so the journal has hard bounds:
- 120 calls per project, oldest dropped first.
- 32,000 characters of output per call, keeping the end, which is where errors and exit codes are.
- 2,000 characters of command or SQL per call.
- One update message per call every 120 ms for live output, never one per chunk of terminal output.
- No timer at rest. While no agent calls a remote tool, the journal costs nothing.
Recording happens at one point: the bridge that every CLI's tool calls go through. That is why it works the same for Claude Code, Codex, Antigravity CLI or any of the other CLIs the app runs, with no code per provider.
The limit we chose: nothing leaves the machine
The journal is kept in the memory of the desktop app and disappears when you quit. It is not synced to our servers, which is unusual for us: almost everything else in AgentsRoom follows your account across computers.
This one does not, on purpose. The output of an env on a server contains secrets. A SELECT on a customers table contains customer data. A tool built to make those visible should not also copy them somewhere new.
The phone can follow the same journal from the agent's profile (mobile app 2.47 and later). The stream goes from your computer to your phone over the end-to-end encrypted link, secrets are masked before they leave (API keys, KEY=value pairs, passwords in URLs, tokens), and nothing is stored on a server. The same call also stays readable in the agent's conversation, as before.
Claude Code audit logs are a different thing
If you searched for "Claude Code audit log", you probably found Anthropic's Compliance API for Claude Enterprise: an activity feed, audit log events and, for local sessions signed in to the Enterprise account, the session transcripts. It is built for administrators and compliance teams, it covers the organization, and you read it after the fact.
That answers "who in the company did what with Claude". It does not answer "which command is my agent running on the database server right now". The two can coexist, and if you work in a company with a compliance requirement, you probably need the first one regardless of what you use for the second.
If you do not use AgentsRoom
You can get a large part of this with what the CLIs already provide.
Log every shell command as it starts. Claude Code hooks can run a command before each tool call. The hooks guide shows the pattern: a PreToolUse hook on the Bash tool that pipes jq -r .tool_input.command into a log file. Run tail -f on that file in a second terminal and you see each command the moment the agent sends it, ssh lines included.
Read the transcript when you need the output. The hook gives you the command, not what the server answered. For that, the session file under ~/.claude/projects/ (or ~/.codex/sessions/ for Codex) has the full result of every call.
Give the agent its own account on the server. A dedicated user makes every connection attributable in the server's auth log, and if your servers run auditd, a rule on execve for that user records each process it starts, on the server side, where the agent cannot skip it.
Keep credentials out of the agent's reach. If the only way to connect is a password the agent has to ask you for, you will see sshpass lines in the chat. Use a key the agent never reads, or a tool that holds the secret for it. We wrote a separate guide on giving an agent a secret without putting it in the prompt.
What this setup does not give you is the link between the three: which agent, on which connection, with which live output, in one place. That is the part we built.
Questions people actually ask
Can I see what Claude Code is doing on a remote server while it works?
In the terminal you see the tool call and, once it finishes, a short result. The full command and its output are written to the session transcript on your disk, which you read afterwards. To watch it as it happens you need something that records each call when it starts: a hook in Claude Code that writes every Bash command to a log file, or an app that runs the remote calls for the agent and shows them live, which is what the Activity tab of AgentsRoom does.
Where does Claude Code keep a record of the commands it ran?
In the session transcript, a JSONL file under ~/.claude/projects/, one folder per project and one file per session. Every tool call is a line with its input and its result. Codex keeps a similar file per session under ~/.codex/sessions/. Both are complete, and both are written for the CLI to resume a session, not for a person to scan.
Is this the same thing as Claude Code audit logs?
No. The audit logs people look for under that name are the organization-level records Anthropic offers on its Enterprise plan through the Compliance API: an activity feed, audit events and, for signed-in sessions, transcripts, read later by an administrator. They answer who did what in the organization. A live view of the commands on one server is a different tool for a different person.
Why not open one terminal tab per command the agent runs?
We tried that path and measured it: an agent working a production issue fired 166 remote commands in one session. One tab per command makes the tab bar useless after ten minutes. What works is one journal per connection, where each call is an entry with its command, its live output, its exit code and its duration.
Does AgentsRoom send the commands and their output to a server?
No. The journal lives in the memory of the desktop app, capped at 120 calls per project, and it is gone when you quit. The phone can follow it from the agent's profile (mobile app 2.47 and later): the stream goes from your computer to your phone over the end-to-end encrypted link, with secrets masked, and nothing is stored on a server.
Which agent commands does the Activity tab not show?
Only calls that go through the AgentsRoom tools are recorded: ssh_exec, ssh_transfer, db_query, db_schema and kube_kubectl. A command the agent runs with its own shell tool, such as a raw ssh or psql line, is in its terminal and its transcript but not in the journal. commands_run and ssh_connect are left out on purpose, because they already open a terminal tab you can watch.
The short version
An agent on a server needs two things from you: a way to work that does not involve your password, and a way for you to see what it does while it does it. The first without the second leaves you reading JSON after the fact. The second without the first gets bypassed by an agent that pastes sshpass lines.
We ended up with one journal per connection, bounded, kept on your machine. If you want to try it, AgentsRoom is free to download, and the SSH connections page shows the setup step by step. If you prefer to stay with your CLI alone, start with the PreToolUse hook and a tail -f: it takes five minutes and you will never again wonder what the last six tool calls were.
Download AgentsRoom
Run all your AI agents, on all your projects, from a single window.
Companion app: monitor your agents on the go
Bring your own: Claude, Codex, Antigravity CLI, or other AI provider.
Push bugs and requests straight to your public backlog.
Keep reading
Keep Claude Code Running After SSH Disconnects: A tmux Recipe
Keep Claude Code alive after an SSH disconnect with tmux. Reconnect to the same process, check persistence, and use AgentsRoom's opt-in setting.
Read the articleTen Agents Ran the Same Type Check at Once. The Fix Was a Directory.
Seventeen coding agents in one checkout, ten tsc processes at the same time, load average 37 and 87 MB of free RAM. A ninety second type check took 7 minutes 36. Here is the measurement, why the machine was not computing, and the small shared lock that fixed it. Copyable into any repository.
Read the articleHow to Give an AI Coding Agent a Secret Without Putting It in the Prompt
An agent needs a Stripe key or a database password to run its command. Paste it in the chat and it lands in the transcript on disk, at the model provider, and sometimes in a commit. The rule we ended up with after three of our own mistakes: a secret reaches an agent through an environment variable and nothing else.
Read the article