See what your OS — and every AI coding agent running on it — is actually doing, via eBPF, explained in plain language instead of syscall jargon.
The name borrows from Argus, the many-eyed watchman of Greek myth, for what the tool actually does: hook the kernel directly (eBPF) while also recognizing when the activity it's watching belongs to an AI agent CLI specifically.
ArgusBPF is a single Go binary. On Linux/amd64 running as root it hooks the kernel directly via eBPF (CO-RE, no kernel headers needed at runtime); everywhere else (other OSes, other architectures, no root) it falls back automatically to a cross-platform polling collector built on gopsutil. The web UI lets you toggle between Professional mode (syscall forms, memory addresses, sector numbers, raw fields) and Plain-language mode (the same events explained in everyday language with analogies).
It's the same idea as tools like CC-Monitor that watch what an AI coding agent does to your machine, applied to the operating system itself, and extended to recognize which AI agent CLI is doing it.
- A single kernel-side dispatcher, not per-process ptrace. One CO-RE program (
bpf/monitor.c) hangs offraw_syscalls/sys_enterplus themodule_load/block_rq_issuetracepoints, covering every process system-wide without the per-process attach overhead ptrace has, and keeps working across kernel versions without rebuilding (no kernel headers needed at runtime). - AI agents recognized by process identity. 10 mainstream AI coding-agent CLIs are matched against a built-in table; recognized events carry an
agentfield, show a badge in the live feed, and get a dedicated timeline lane so you can see what one agent actually touched. - TLS/DNS/SQL plaintext capture. eCapture-style uprobes on
SSL_read/SSL_write/getaddrinfo/exec_simple_queryrecover plaintext in the target process's own memory, before/after encryption, with no MITM proxy or certificate handling needed. - Two renderings per event. Every event gets a real syscall-form professional rendering and a separately generated plain-language explanation with an everyday analogy, produced by an offline template/lookup engine (no LLM calls, fully deterministic, works with no network at all).
- One binary, cross-platform. Pure Go, no CGO anywhere (SQLite included). Root + Linux/amd64 gets the full eBPF pipeline; any other OS, architecture, or no root falls back to a gopsutil-based poller.
- AI agent recognition — every event's process is checked against a table of mainstream AI coding-agent CLIs (Claude Code, Codex, Cursor, Gemini CLI, Grok CLI, Aider, OpenCode, ZCode, OpenClacky, Antigravity CLI — the same roster CC-Monitor tracks on its dev branch); matched events carry an
agent/agent_displayfield, get a 🤖 badge in the live feed, and the timeline page has a dedicated "by AI agent" lane so you can see exactly what an agent touched, separate from everything else running on the box. - Live event feed — every exec, file open/write/unlink/rename, network connect/listen, mmap/mprotect/ptrace/cross-process memory access, kernel module load, and block-device IO, streamed over WebSocket.
- Risk rules — a small JSON ruleset (editable, user-overridable) flags things like reading
/etc/shadow, W+X memory pages,ptraceattach, cross-process memory writes, kernel module loads, SSH activity, and more, at info/low/medium/high severity. - Plain-language explanations — every event gets both a technical one-liner (
mprotect(addr=0x7f.., prot=RWX)) and a plain-English explanation with an everyday analogy, generated offline by a template/lookup engine (no LLM calls, fully deterministic). - eCapture-style application probes — best-effort uprobes on
getaddrinfo(DNS), OpenSSLSSL_read/SSL_write(TLS plaintext), and Postgresexec_simple_query(SQL text), attached automatically when the target library/binary is present; each one degrades gracefully (and says so in/api/info) if it isn't. - Full web dashboard — overview with live CPU/memory/disk/network charts, live event table, swimlane timeline (by category, by process, or by AI agent), network connections, disk IO (including a sector-level scatter plot), per-process memory maps (
/proc/<pid>/mapsvisualised and explained region-by-region), a process tree, an alerts view, and a glossary of terms — styled like Grafana (dark panel grid, legends, time-range picker) but self-contained, no Grafana install required. - Cross-platform by design — pure Go, no CGO (SQLite via
modernc.org/sqlite). Builds for darwin/windows/linux on amd64/arm64; only the eBPF collector is linux/amd64-specific, everything else runs everywhere. - Optional PTY web terminal (
--enable-terminal, off by default) — open a real terminal right in the dashboard and run anything in it (an AI agent CLI, a shell), with multiple concurrent sessions and a grid view to watch several at once. This is a genuinely different trust model from the rest of this read-only tool — it can spawn and drive real processes — which is why it's gated behind an explicit flag and not just the dashboard's own UI. If you turn it on, also set--tokenand keep--listenbound to localhost (the default) or your own reverse proxy — anyone who can reach the port can open a shell. - MCP server for AI clients (
--mcp) — runargusbpf --mcpas a Model Context Protocol stdio server so an AI assistant (Claude Code, Claude Desktop, any MCP client) can query this machine directly:hardware_info(CPU/memory/disk/host),busybox_applets(what BusyBox actually provides, useful on embedded/automotive images where most of/binis one BusyBox binary),recent_eventsandevent_stats(the same captured activity the dashboard shows, filterable by category/risk/agent/time window). It reads the dashboard's own SQLite database read-only, so it needs no root, no open port, and no--token— see Using the MCP server below.
Recognition is by process comm/exe identity (see internal/agents), mirroring the roster CC-Monitor tracks on its dev branch. Filter any of these in the API/UI via ?agent=<id>, or watch the timeline's "by AI agent" lane.
| Agent | id | Detected via (comm / exe) |
|---|---|---|
| Claude Code | claude-code |
claude |
| Codex CLI | codex |
codex, codex-x86_64-*, codex-aarch64-* |
| Cursor | cursor |
cursor-agent |
| Gemini CLI | gemini-cli |
gemini |
| Grok CLI | grok-cli |
grok |
| Aider | aider |
aider |
| OpenCode | opencode |
opencode |
| ZCode | zcode |
zcode, zcode-cli |
| OpenClacky | openclacky |
openclacky, clacky |
| Antigravity CLI | antigravity-cli |
agy, antigravity-cli |
New agents are a one-line addition to internal/agents/agents.go — PRs welcome for anything missing.
# Build (clang/bpftool not required — the eBPF object ships pre-built)
make build
# Run as root for the eBPF collector; without root it auto-falls-back to polling
sudo ./argusbpf
# Open the dashboard
open http://127.0.0.1:1024Useful flags:
| Flag | Default | Meaning |
|---|---|---|
--listen |
127.0.0.1:1024 |
HTTP listen address — defaults to localhost-only; passing a non-loopback address (0.0.0.0:1024, a LAN IP, :1024) opens it up to the network and logs a startup warning when you do |
--token |
(none) | Require X-Token header / ?token= query param |
--db |
~/.argusbpf/events.db |
SQLite database path |
--rules |
~/.argusbpf/rules.json |
Override the built-in risk ruleset |
--enable-terminal |
false |
Enable the PTY web terminal (see Features above — set --token too if you turn this on) |
--mcp |
false |
Run as an MCP stdio server instead of the web dashboard (see Using the MCP server) |
argusbpf --mcp runs as a standalone MCP stdio server instead of the dashboard — it reads the same SQLite database the dashboard writes to (--db if you're using a non-default path) and exposes four tools: hardware_info, busybox_applets, recent_events, event_stats. It doesn't need root, doesn't open a network port, and doesn't need --token — a client spawns it as a short-lived subprocess per the protocol's normal stdio transport.
For Claude Code, add it with:
claude mcp add argusbpf -- /usr/local/bin/argusbpf --mcpOr configure it directly (Claude Code's .mcp.json, Claude Desktop's claude_desktop_config.json, or any other MCP client):
{
"mcpServers": {
"argusbpf": {
"command": "/usr/local/bin/argusbpf",
"args": ["--mcp"]
}
}
}If the dashboard uses a non-default --db path, pass the same one here ("args": ["--mcp", "--db", "/path/to/events.db"]) so the MCP server reads the right file. The dashboard doesn't need to be running for hardware_info/busybox_applets to work (they read the live machine directly); recent_events/event_stats need the database to already exist, which means the dashboard has to have run at least once.
A pre-built internal/collector/monitor_x86_bpfel.o is committed, so make build never needs clang. If you change bpf/monitor.c:
make vmlinux # dump this kernel's BTF -> bpf/vmlinux.h (needs bpftool)
make bpf # recompile monitor.c -> the .o/.go pair (needs clang, llvm-strip)
make buildSee DESIGN.md for the full design: event model, collection pipeline, risk rules, the plain/professional explanation engine, and the HTTP/WebSocket API contract used by web/. See CHANGELOG.md for release history.
collector (eBPF | poller) -> pipeline (rules + explain + 1s aggregation) -> SQLite + WebSocket hub -> web UI
| OS / arch | Collector | Notes |
|---|---|---|
| Linux/amd64, root | eBPF (CO-RE) | full detail: syscall args, memory addresses, sector numbers |
| Linux/amd64, non-root | polling | automatic fallback |
| Linux/arm64 | polling | eBPF syscall-number table is amd64-specific for now |
| macOS, Windows | polling | process/network diffing via gopsutil |
- MySQL
dispatch_commandSQL capture isn't implemented — its argument layout is too version-fragile to ship safely; Postgres (exec_simple_query, a stable single-char*signature) is. - No
bash readlinecommand-audit uprobe yet. - Inbound connections (
accept) aren't individually captured by the eBPF path; the disk page's "top files by IO" has no data source yet (only per-process IO and the sector scatter plot). - Distro-packaged Postgres binaries are typically LTO-built and stripped, so
exec_simple_queryisn't attachable by name;install.sh's uprobe logic falls back to resolving its address from a matching-dbgsymdebug package when one is installed, and that capability is simply unavailable without it.









