Audit Trail
JSON-lines log of every intercepted command and its outcome
shellfirm records every intercepted command in a local audit log. Each entry includes the command, matched patterns, severity, challenge type, outcome, context labels, and blast radius data. The log is in JSON-lines format (one JSON object per line), making it easy to parse with standard tools.
Log location
The audit log is stored at ~/.config/shellfirm/audit.log (in the same directory as your settings file).
Viewing the log
shellfirm audit show
This prints the raw JSON-lines content. You can pipe it to jq for formatted output:
shellfirm audit show | jq .
Clearing the log
shellfirm audit clear
This permanently deletes the audit log file.
Log entry format
Each entry is a JSON object with these fields:
{
"event_id": "abc123-def456",
"timestamp": "2026-02-15T10:00:00Z",
"command": "git push --force origin main",
"matched_ids": ["git:force_push"],
"challenge_type": "Yes",
"outcome": "Denied",
"context_labels": ["branch=main", "ssh=true"],
"severity": "High",
"agent_name": null,
"agent_session_id": null,
"blast_radius_scope": "PROJECT",
"blast_radius_detail": "Force-pushes 5 commits to origin/main"
}
Fields
| Field | Type | Description |
|---|---|---|
event_id | string | Unique identifier for correlating pre/post challenge entries |
timestamp | string | ISO 8601 UTC timestamp |
command | string | The full command that was intercepted |
matched_ids | string[] | Pattern IDs that matched (e.g., ["git:force_push"]) |
challenge_type | string | Challenge presented (Math, Enter, Yes) |
outcome | string | Result of the challenge (see below) |
context_labels | string[] | Detected context (e.g., ["branch=main", "ssh=true"]) |
severity | string | Highest severity among matched checks |
agent_name | string? | AI agent name (if command came from an agent) |
agent_session_id | string? | AI agent session ID |
blast_radius_scope | string? | Blast scope: RESOURCE, PROJECT, NAMESPACE, MACHINE |
blast_radius_detail | string? | Human-readable blast radius description |
Outcome values
| Outcome | Meaning |
|---|---|
Allowed | User solved the challenge; command was executed |
Denied | Command was on the deny list or user failed the challenge |
Skipped | Check matched but severity was below min_severity threshold |
Cancelled | Written before the challenge prompt; if the process is killed during the challenge (Ctrl+C), this is the only entry that survives |
Event correlation
Each interception produces two log entries sharing the same event_id:
- Pre-challenge entry with outcome
Cancelled-- written before the challenge prompt is shown - Post-challenge entry with outcome
Allowed,Denied, orSkipped-- written after the user responds
If the user presses Ctrl+C during the challenge, only the Cancelled entry exists. This ensures no command goes unlogged, even if the process is terminated.
Configuration
Enable or disable audit logging in ~/.config/shellfirm/settings.yaml:
audit_enabled: true # enabled by default
Or open the interactive config editor:
shellfirm config edit
Querying the log
Since the audit log is JSON-lines format, you can query it with standard tools:
Find all denied commands
shellfirm audit show | jq 'select(.outcome == "Denied")'
Find all Critical severity events
shellfirm audit show | jq 'select(.severity == "Critical")'
Find commands from a specific date
shellfirm audit show | jq 'select(.timestamp | startswith("2026-02-15"))'
Find all agent-originated commands
shellfirm audit show | jq 'select(.agent_name != null)'
Count events by outcome
shellfirm audit show | jq -r '.outcome' | sort | uniq -c | sort -rn
Find all commands with MACHINE blast scope
shellfirm audit show | jq 'select(.blast_radius_scope == "MACHINE")'
Compliance use cases
The audit trail is designed for compliance and incident investigation:
- SOC2 auditing -- Demonstrate that destructive commands require explicit confirmation
- Incident response -- See exactly what commands were executed, when, and by whom
- Policy enforcement -- Verify that deny-listed patterns are being blocked
- Agent oversight -- Track what AI agents attempted to execute
- Blast radius tracking -- Understand the scope of approved destructive commands