← Tim Suskov

I gave AI agents a flight recorder

Argus runs any agent and shows you, live, everything it touches on your Mac — every file, every process, every network connection, with red flags on the paths that matter. Then I ran a real Claude Code session under it.

299
files read by one 2-min Claude Code task
3
keychain paths it touched — flagged red
61
processes in its tree
0
kernel extensions or entitlements
Argus on GitHub brew install tsuskov/tap/argus — then run any agent under it: argus -- <agent command>. MIT, macOS.

We've all normalized something strange: we download agents and MCP servers off the internet and hand them a shell. They run as you. Everything you can read — your SSH keys, your browser cookies, every .env you ever scattered across your projects — they can read. And if you ask yourself what an agent actually did during that twenty-minute session, the honest answer is: you scrolled past it.

This isn't hypothetical anymore. Last year someone backdoored postmark-mcp, an npm MCP server, to quietly BCC outgoing mail to an attacker's domain; security scans of public MCP servers keep finding a scary fraction with critical issues. The response so far is mostly "review the code" (nobody does) or "run it in a VM" (nobody does that either).

So I built the thing I actually wanted: a flight recorder. Not a sandbox, not a firewall — first, just the truth about what happened.

argus running a malicious decoy agent: a live event stream, red SENSITIVE flags on ~/.ssh and .env, then a session summary

What Argus does

argus -- <agent command> starts your agent and streams every file read and write, every spawned process, every deletion and rename, and every network connection — live, filtered to that agent's process tree, so you see the agent and nothing else. Touches on sensitive paths (~/.ssh, ~/.aws, ~/.gnupg, keychains, browser cookies, .env files, .netrc, GitHub CLI credentials, your Messages database) are flagged red the moment they happen. On a terminal you get a TUI with a by-directory view; in a pipe you get lines, or JSON with --json. Every session ends with a report: argus-report.md for you, argus-report.json for your tooling.

Two minutes of Claude Code, measured

I gave Claude Code a small, ordinary task in one of my Rust repos — read the codebase, run the tests, explain the architecture — and ran it under Argus. 110 seconds, headless. The unedited summary:

argus: 299 files read · 36 written · 18 deleted · 61 processes executed · 2 hosts contacted argus: ⚠ 3 sensitive paths touched ⚠ /Library/Keychains/System.keychain ⚠ /System/Library/Keychains/SystemTrustSettings.plist ⚠ /Users/…/Library/Keychains/login.keychain-db

Four things I did not know before I watched:

None of this is a scandal — it's the opposite. It's what your agent does every single session, invisible until you point a flight recorder at it. The interesting question is what the other tools in your stack look like under the same lens.

Watching a malicious agent work

The repo ships with a decoy — a six-step "malicious agent" that does what a compromised tool would do: read an SSH private key, read a .env, spawn children that write files, rename, delete, and phone home. It's also the test fixture; every Argus milestone had to catch all of it before it counted as done. Here's the actual session report, unedited:

argus: 35 files read · 8 written · 6 deleted · 13 processes executed · 1 host contacted argus: ⚠ 3 sensitive paths touched ⚠ …/fake_home/.env ⚠ …/fake_home/.ssh ⚠ …/fake_home/.ssh/id_ed25519

Total runtime: 2.9 seconds. That's how long a rogue dependency needs to take your key and exfiltrate it — and exactly the kind of thing that's invisible in a wall of agent output and obvious in a red line.

The unedited detail is my favorite part. A six-line shell script "reads 35 files"? Yes — and the report shows they're real: curl pulls in /etc/ssl/cert.pem and openssl.cnf, the shell walks locale files, something consults the timezone database. Nothing is summarized or guessed; if a process in the tree opened it, it's in the list. The signal lives in the red lines on top.

How it works (and the trick that makes it installable)

macOS has a beautiful audit API — Endpoint Security — and a catch: consuming it normally requires a signed system extension with an Apple-granted entitlement. That's why most tools in this space are either commercial EDR or a kernel-adjacent science project.

The trick: since macOS 13, Apple ships /usr/bin/eslogger — their own signed ES client that prints events as JSON. Argus subscribes to eight event types (exec, fork, exit, open, create, write, unlink, rename) through it, follows fork/exec to maintain the agent's pid tree, and drops everything outside the tree. No kext, no entitlement, no third-party daemon — the privileged component is Apple's own binary. The cost is honest friction: eslogger needs sudo and Full Disk Access, once.

Two details I care about:

War story, because these are the fun part: my first stop-gate raised SIGSTOP in pre_exec, between fork and exec. Every single run deadlocked — Command::spawn in Rust blocks on a pipe until the child execs, and my child had stopped itself right before doing that. The parent waited for the exec, the child waited for a SIGCONT the parent would never send. A sample of the hung process made it obvious in one stack trace. Moving the stop after the exec (stop yourself, then exec "$@" on continue — same pid throughout) fixed it, and waitpid(WUNTRACED) now confirms the stop before the run proceeds, so the race can't come back.

What it's not (yet)

v0.1 observes; it doesn't block. That's a deliberate first release: a recorder you actually run beats a policy engine you don't. v0.2 is the enforcement half, and the design is already fixed:

Try it

brew install tsuskov/tap/argus, or build from source — it's ~1.2k lines of Rust, small enough to read in an evening, MIT-licensed. Run the decoy (argus -- sh tests/decoy-agent.sh) to see the red flags, then run it on your actual agent and read the report. I'd genuinely like to hear what your agents turn out to be doing — that's the whole point of a flight recorder.