Audit Log
Query, export, and understand Beekeeper's NDJSON decision log.
Every decision Beekeeper makes (allow, warn, block, quarantine, posture override, and config change) is appended to an NDJSON audit log. Each line is a single JSON object.
A separate, opt-in corpus log records confirmed incidents for the local
first-responder loop. It is a different file (corpus/beekeeper-corpus.ndjson),
also append-only and owner-only and written through the same redaction step. It
carries a richer four-layer record (behavior, decision, outcome, context) in the
frozen push-envelope shape rather than the flat decision record described here,
and it never leaves the machine. See Security and
Configuration.
Location
| OS | Audit log |
|---|---|
| Linux / macOS | ~/.beekeeper/audit/beekeeper.ndjson |
| Windows | %APPDATA%\beekeeper\audit\beekeeper.ndjson |
The log is a single beekeeper.ndjson file with owner-only permissions
(0600), written append-only. The shipped binary does not rotate or compress
the audit log; there are no dated per-day files. Query it with the
beekeeper audit subcommands below rather than reading dated files directly.
Reading the log
beekeeper audit tail # stream live decisions (Ctrl+C to stop)beekeeper audit tail --no-follow # dump existing records and exitTo browse the same records interactively, with one color-coded row per decision
and an expandable per-record view of the full decision logic (corroboration
sources, catalog matches, rules, posture overrides, and Sentry evidence), open the
TUI Dashboard and run audit tail from the command palette.
Querying
beekeeper audit query --since 24h --decision block --limit 50beekeeper audit query --since 2026-06-01T00:00:00Z --agent claude-code --tool Bash--sinceaccepts a Go duration (24h,168h) or an RFC3339 timestamp--agent,--tool,--decision(allow|warn|block), and--limitfilter the results
Exporting
beekeeper audit export --format ndjsonbeekeeper audit export --format csv --since 7dbeekeeper audit export --format otlp--format is required and accepts ndjson, csv, or otlp. The same
--since / --agent / --tool / --decision filters apply.
Posture override records
A scoped install-posture override (beekeeper posture allow / enforce, see the
CLI Reference) writes a distinct record_type:"posture_override"
record with these key fields:
| Field | Description |
|---|---|
posture_override_action | allow_once | allow_always | enforce_block | enforce_warn |
posture_package | the package an allow override exempts (empty for an enforce) |
posture_ecosystem | the ecosystem the override is scoped to (empty matches any) |
posture_rule | the rule scope: release-age, lifecycle, git-remote, or empty (all rules) |
reason | the operator-recorded justification (required for allow_always) |
A posture allow is posture-scoped: it silences a posture warn for the package but
never downgrades a catalog or corroboration malware block.
The Sentry layer also writes a sentry_install_observed record (SENTRY-009) when a
monitored descendant spawns a package-manager install. It is detection-only
(severity info); Sentry never blocks or quarantines. See
Security.
The nudge record type that earlier versions produced is no longer written as of
v1.1.0 (the package-manager nudge was removed). The deprecated nudge_* fields are
retained unpopulated for corpus schema compatibility only.
Record types
Each line carries a record_type. The shipped binary writes:
record_type | Written by |
|---|---|
policy_decision | The beekeeper check hook and the MCP gateway: the allow/warn/block/quarantine decision for a tool call. This is the default record. |
tool_result | The PostToolUse hook (beekeeper audit-record): the outcome of a tool call that ran. |
posture_override | A scoped install-posture override from beekeeper posture allow / enforce (see above). |
sentry_install_observed | A Sentry install observation (SENTRY-009): a monitored descendant spawned a package-manager install. Detection-only. |
sentry_alert | A Sentry behavioral rule hit (detection-only). |
llmf_alert | A LlamaFirewall prompt-injection or unsafe-code scan result. |
config_change | A beekeeper config set change. |
The nudge and version_drift record types that earlier versions emitted are no
longer written as of v1.1.0.
The decision field is one of allow, warn, block, or alert (alert marks
a Sentry detection-only record). A quarantine carries quarantine: true alongside
its decision.
Record examples
{"record_type":"policy_decision","decision":"block","tool_name":"Bash","reason":"corroborated: 2 sources flag this package","agent_name":"claude-code"}
{"record_type":"posture_override","posture_override_action":"allow_always","posture_package":"left-pad","posture_rule":"release-age","reason":"internal mirror"}
{"record_type":"sentry_install_observed","decision":"alert","severity":"info","reason":"package-manager install observed: npm"}Remote sinks, rotation, and the redaction caveat
In this release the only active audit sink is the local file. It is
owner-only (0600) and append-only.
The internal/audit package also implements remote syslog / OTLP / HTTPS sinks
and size-based rotation, and the schema accepts an audit config block (sinks,
syslog_address, otlp_endpoint, https_endpoint, max_size_bytes,
retention_days). But no shipped code path wires them up: the live writer
fans out to no remote sink and does not rotate, so setting those keys has no
effect today. Treat shipping audit data off-host as something you do yourself by
forwarding the file.
Redaction is field-scoped, not content-scanning. The decision
Reasonfield and raw/rewritten package-manager commands are redacted, but Sentry-derived fields (accessed file paths, network destinations, process exe paths, correlated extension IDs) and catalog coordinates are written verbatim, and the behavioral-watch audit path does not route throughRedactRecordat all. A credential embedded in a watched file path or network destination is therefore present in the on-disk log unscrubbed. The file is owner-only (0600); account for this before you forward the audit log off-host.