Guide 8 min read

How to Audit Shell Commands Claude Code and Cursor Run

Record, search, and audit the shell commands Claude Code, Cursor, and other supported agents report, with a failed-run investigation and clear capture limits.

Madhubalan Appachi Madhubalan Appachi · Published · Updated

When you hand a task to Claude Code or Cursor, it doesn't just edit files — it runs shell commands. Installs, migrations, git operations, test runs, the occasional rm. Most of these scroll past in a tool panel and are hard to find again once the session ends. If something breaks an hour later, you want a record of what the agent actually ran. This guide shows how to capture the shell commands your supported agent integrations report, investigate a failure with them, and understand what the record does not contain.

Why agent commands are hard to see

  • They don't land in your shell history. Agents usually run commands in their own subprocess, so ~/.zsh_history never sees them.
  • The agent UI is a chat log. The tool-call record lives inside the conversation, mixed in with file reads, edits, and prose. It isn't something you can filter by exit code or directory.
  • You can't tell who ran what. Even when commands do hit your history, there's nothing marking which were yours and which were the agent's.

The result is a visibility gap exactly where you'd want the most accountability: automated commands running with your permissions.

Record commands with their executor and prompt

Suvadu stores captured shell and agent commands in a local SQLite database. Each record includes the executor (for example claude-code or cursor), working directory, timestamp, and the exit code when the source reports one. Prompt text is attached only when the configured integration captures prompt events; environment-variable detection alone does not capture a prompt.

1. Install Suvadu

curl -fsSL https://downloads.appachi.tech/suvadu/install.sh | bash

The installer provides the binary and prints shell-setup instructions. It does not modify or reload Zsh/Bash, so complete the appropriate installation and shell-integration steps before expecting terminal commands to be recorded.

2. Connect your agents

suv init claude-code
suv init cursor

Each command installs that agent's hooks, so the shell commands it reports are recorded and attributed. Relaunch Claude Code and restart Cursor afterwards so they load the new hooks. Other agents, restart requirements, and per-agent differences are covered in agent integration and the compatibility matrix.

3. Review what the agent ran

# Claude Code commands recorded today, newest first
suv history --executor claude-code --after today

# Interactive search, scoped to Claude Code's failed commands
suv search --executor claude-code --failed

The search TUI lets you narrow by executor, directory, time, and exit code. An explicit --executor filter shows agent commands even though they are hidden from everyday Ctrl+R recall.

Walkthrough: investigate a failed agent run

Here is a synthetic but realistic case. You asked Claude Code to "add rate limiting to the login route" in ~/src/shop-api. It reported success, but CI on your branch fails in the test suite. You want to know what the agent actually ran before you start guessing.

Step 1: Get the report for this project

From the directory the agent worked in, generate today's report for Claude Code. --here matches that exact directory, not its subdirectories.

$ suv agent report --executor claude-code --here

═══════════════════════════════════════════════════════
  AGENT ACTIVITY REPORT — Sep 18, 2026
═══════════════════════════════════════════════════════

  Period:     14:02 — 14:09
  Agents:     claude-code (7 cmds)
  Success:    5/7 (71.4%)
  Risk:       1 high

───────────────────────────────────────────────────────
  ⚠ HIGH RISK COMMANDS
───────────────────────────────────────────────────────
  [claude-code]  npm install express-rate-limit
             ~/src/shop-api · 14:03 · exit 0
             Category: package-install

───────────────────────────────────────────────────────
  📦 PACKAGES INSTALLED
───────────────────────────────────────────────────────
  npm: express-rate-limit

───────────────────────────────────────────────────────
  ✘ FAILED COMMANDS (2)
───────────────────────────────────────────────────────
  [claude-code]  npm test -- login                          exit 1  14:05
  [claude-code]  npm test                                   exit 1  14:08

═══════════════════════════════════════════════════════

Two things stand out. The agent added a dependency, and it ran the full test suite once, which failed. A failed scoped run like the one at 14:05 is normal, since agents often run, fix, and rerun (the report lists failures, not the passing reruns). The 14:08 failure is the interesting one: nothing recorded after it shows the full suite passing. The high label on the install is informational: risk assessment flags package installs because they bring in external code, not because this one is wrong.

Step 2: List the failures with timestamps

$ suv history --executor claude-code --exit-code 1 --here
2026-09-18 14:08:41  ✗1       0ms  ~/src/shop-api        npm test
2026-09-18 14:05:12  ✗1       0ms  ~/src/shop-api        npm test -- login

The 0ms is expected. Claude Code's hook events don't include a duration, so Suvadu records the time the hook was received rather than inventing a runtime. Integrations that report duration, such as Cursor's shell-execution hook, show real values here.

Step 3: Connect the failure to the prompt

suv agent prompts --executor claude-code --here

The Prompt Explorer lists captured prompts for the period. Select the rate-limiting prompt and press Enter to see the commands recorded under it, with path, time, exit code, and executor. Ctrl+S jumps to that prompt's session timeline.

Step 4: Read what the agent said about it

suv sessions

In the session browser, Ctrl+T cycles to AI sessions. A Claude Code timeline interleaves your prompts, the assistant's text responses, the recorded commands, and the model in use. In this case, the assistant's final message is where you'd find out whether it noticed the 14:08 failure and called it "unrelated", or never mentioned it. See the sessions guide for how to read each field.

Step 5: Reproduce the failure yourself

Suvadu stores the command line, not its output, so the error text isn't in the record. You now know the exact command, directory, and time, though, so rerun npm test in ~/src/shop-api and compare the result with the agent's final message. If you use an MCP-connected assistant, you can also ask it "what failed in this project today?" and it can call Suvadu's what_failed tool, which groups recent failures by the prompt that triggered them.

What gets captured, and what doesn't

An audit trail is only useful if you know its edges. Suvadu records what its hooks are told about; it does not watch processes independently.

Commands

  • Dedicated integrations (Claude Code, Codex, Cursor, OpenCode, pi) record shell commands from the host's own shell-tool events. Claude Code and Codex hooks capture only the Bash tool; Cursor uses its shell-execution hook; OpenCode and pi use their bash tool events.
  • Shell hooks record commands typed in an interactive Zsh or Bash session that has loaded suv init zsh or suv init bash. IDE terminals such as VS Code, Cursor's terminal, Windsurf, and Antigravity are labeled by environment detection.

Prompts and sessions

  • Prompt text is captured for Claude Code, Codex, Cursor, OpenCode, and pi, because those integrations receive prompt events. It is redacted and length-capped before storage.
  • Full sessions, including assistant responses, observed models, and provider-reported token counts, are imported for Claude Code, Codex, and OpenCode. Claude Code and Codex import at the end of each turn; OpenCode imports when the session goes idle.
  • Environment-detected tools, such as Antigravity and IDE terminals, get executor labels but no prompts.

Not captured

  • Non-shell tool calls. File reads, edits, searches, and web fetches made through an agent's own tools are not shell commands, so they don't appear as command records.
  • Command output. Stdout and stderr are not stored. Claude Code session import also excludes tool results, thinking blocks, attachments, and file contents.
  • Commands with no event. If the host doesn't emit a hook (for example, hooks not yet trusted in Codex, the agent not relaunched after suv init, or a crash before the event fires), there is nothing to record.
  • Unhooked shells. A command run by an agent without a dedicated integration, in a non-interactive shell that doesn't load Suvadu's hooks, is not recorded.
  • Commands inside commands. Suvadu records the command line that was run. If that line runs a script, the script's internal commands are not recorded separately.
  • Child sessions. Sessions started by a sub-agent are not merged into the parent session's view.
  • Paused or excluded recording. Anything run while recording is disabled or paused, or matching one of your command exclusion patterns, is intentionally skipped.

Exit codes are only as precise as the host event. Claude Code reports failures through a separate event whose error message Suvadu parses; some Codex events carry no exit code, and those records show a neutral marker rather than a guessed code. If a command you expected is missing, run suv doctor to check the installed hooks, and see the compatibility matrix for per-agent gaps.

Auditing for risk

Visibility is step one; triage is step two. Suvadu's risk assessment flags destructive or sensitive commands — recursive deletes, hard resets, force pushes, package installs, piping the network into a shell — so you can scan an agent's commands for the ones that deserve attention instead of reading every line. It is pattern-based and informational; it never blocks a command unless you wire suv guard into a hook yourself.

For a higher-level view, agent reports and the agent dashboard summarise recorded agent activity over a period: how many commands, how many failed, and which were flagged.

Replaying a session

When you need the chronological story of a single run, command replay walks through recorded commands in order, with directories and exit codes. For prompts and responses alongside the commands, use suv sessions.

Turning history into agent memory

Once your history knows about agents, a connected AI client can query it through Suvadu's local MCP server. The returned records are available to the client and may be sent to its provider under the client's settings.

The takeaway

AI agents run real commands with your permissions. With executor attribution, prompt context where the integration provides it, and risk flags, you can answer "what did it run, where, and did it fail?" from a local record, and you know which questions the record can't answer.

Next steps: Set up your agent integration →  ·  Agent report reference →

Madhubalan Appachi
Madhubalan Appachi

Builder of Suvadu. Writes Rust, thinks about shell history more than most people, and believes developer tools should be local-first.