$ shellfirm

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

FieldTypeDescription
event_idstringUnique identifier for correlating pre/post challenge entries
timestampstringISO 8601 UTC timestamp
commandstringThe full command that was intercepted
matched_idsstring[]Pattern IDs that matched (e.g., ["git:force_push"])
challenge_typestringChallenge presented (Math, Enter, Yes)
outcomestringResult of the challenge (see below)
context_labelsstring[]Detected context (e.g., ["branch=main", "ssh=true"])
severitystringHighest severity among matched checks
agent_namestring?AI agent name (if command came from an agent)
agent_session_idstring?AI agent session ID
blast_radius_scopestring?Blast scope: RESOURCE, PROJECT, NAMESPACE, MACHINE
blast_radius_detailstring?Human-readable blast radius description

Outcome values

OutcomeMeaning
AllowedUser solved the challenge; command was executed
DeniedCommand was on the deny list or user failed the challenge
SkippedCheck matched but severity was below min_severity threshold
CancelledWritten 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:

  1. Pre-challenge entry with outcome Cancelled -- written before the challenge prompt is shown
  2. Post-challenge entry with outcome Allowed, Denied, or Skipped -- 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