Audit Trail for Automation
Every automated command is logged with session ID, agent name, and full context
When AI agents and automation scripts run commands through shellfirm, every interaction is recorded in the audit log. This creates a complete trail of what was executed, what was blocked, and why.
What gets logged
Every command evaluated by shellfirm (whether via shell hook, MCP server, or CLI check) produces an audit event with:
| Field | Description |
|---|---|
event_id | Unique identifier for correlating pre/post challenge entries |
timestamp | ISO 8601 timestamp (UTC) |
command | The full command string |
matched_ids | List of matched pattern IDs (e.g., ["git:force_push"]) |
challenge_type | The challenge type applied (Math, Enter, Yes, or Deny) |
outcome | ALLOWED, DENIED, SKIPPED, or CANCELLED |
context_labels | Runtime context labels (e.g., ["branch=main", "ssh=true"]) |
severity | Highest severity among matched checks |
agent_name | Name of the AI agent (if applicable) |
agent_session_id | Session ID of the agent connection (if applicable) |
blast_radius_scope | Impact scope (RESOURCE, PROJECT, MACHINE) |
blast_radius_detail | Human-readable impact description |
Log format
Audit events are stored as JSON-lines (one JSON object per line) in ~/.shellfirm/audit.log:
{"event_id":"a1b2c3","timestamp":"2026-02-23T14:30:00Z","command":"git push --force origin main","matched_ids":["git:force_push"],"challenge_type":"Yes","outcome":"DENIED","context_labels":["branch=main"],"severity":"High","agent_name":"claude-code","agent_session_id":"sess-xyz-789","blast_radius_scope":"PROJECT","blast_radius_detail":"Overwrites remote branch history"}
{"event_id":"d4e5f6","timestamp":"2026-02-23T14:30:05Z","command":"git push --force-with-lease origin main","matched_ids":[],"challenge_type":"Math","outcome":"ALLOWED","context_labels":["branch=main"],"severity":"Medium","agent_name":"claude-code","agent_session_id":"sess-xyz-789"}
Agent-specific fields
When commands come through the MCP server, the audit log includes agent identification:
- agent_session_id -- a unique ID generated per MCP server session. All commands from the same agent connection share this ID, making it easy to trace an agent's full command history.
- agent_name -- identifies which agent originated the command (when provided by the client).
Querying the audit log
View recent events
shellfirm audit list
Search for specific patterns
# Find all denied commands
shellfirm audit search --outcome denied
# Find all commands from a specific agent session
shellfirm audit search --session sess-xyz-789
Using jq for analysis
Since the log is JSON-lines, you can use jq for powerful queries:
# All denied commands
cat ~/.shellfirm/audit.log | jq -c 'select(.outcome == "DENIED")'
# Commands from a specific agent session
cat ~/.shellfirm/audit.log | jq -c 'select(.agent_session_id == "sess-xyz-789")'
# High severity events in the last 24 hours
cat ~/.shellfirm/audit.log | jq -c 'select(.severity == "High" or .severity == "Critical")'
# Count outcomes by type
cat ~/.shellfirm/audit.log | jq -r '.outcome' | sort | uniq -c | sort -rn
# List all unique agent sessions
cat ~/.shellfirm/audit.log | jq -r '.agent_session_id // empty' | sort -u
Correlating events
Each command evaluation produces up to two audit events with the same event_id:
- Pre-challenge entry with outcome
CANCELLED-- written before the challenge prompt. If the user hits Ctrl+C during the challenge, this is the only entry. - Post-challenge entry with outcome
ALLOWED,DENIED, orSKIPPED-- written after the challenge completes.
For agent/MCP commands (which are non-interactive), only the final outcome entry is written.
Integration with monitoring
Forward to SIEM
Tail the audit log and forward to your SIEM tool:
tail -f ~/.shellfirm/audit.log | your-siem-forwarder
Datadog / Splunk / ELK
Since the log is JSON-lines, it can be ingested directly by most log aggregation platforms:
# Filebeat configuration example
- type: log
paths:
- ~/.shellfirm/audit.log
json.keys_under_root: true
json.add_error_key: true
Alerting on denied commands
Set up alerts for patterns that indicate an agent misbehaving:
# Alert when the same agent session has more than 5 denials
cat ~/.shellfirm/audit.log \
| jq -r 'select(.outcome == "DENIED") | .agent_session_id // empty' \
| sort | uniq -c | sort -rn \
| awk '$1 > 5 {print "ALERT: Agent session " $2 " has " $1 " denied commands"}'