Skip to main content
The explain --json command returns a structured trace of every analysis step CC Safety Net performs on a command. This page documents that JSON shape, for anyone scripting against the trace or building tooling on top of it. For the command itself, see CLI Commands.
npx cc-safety-net explain --json "git checkout -- file.txt"

ExplainResult

The top-level object returned by explain --json.
FieldTypeDescription
result"blocked" | "allowed"Final outcome for the command
reasonstringThe block reason, present when result is blocked
segmentstringThe specific segment that triggered the decision
traceExplainTraceThe trace container with top-level and per-segment steps
customRuleobjectWhen a custom rule matched: id, optional rulebook, source, and override
configSourcestringThe config file the effective config was loaded from
configValidbooleanWhether the loaded config validated cleanly

ExplainTrace

FieldTypeDescription
stepsTraceStep[]Top-level steps (for example the initial parse)
segmentsobject[]Per-segment entries, each with its own steps array

TraceStep variants

Each step in a trace is a TraceStep discriminated by its type field. The table below lists every variant and what it captures. Parse the type first, then read the variant’s key fields.
typeKey fieldsWhen it appears
parseinput, segmentsInitial shell split into token segments
env-stripinput, envVars, outputEnvironment assignments stripped from the segment front (values redacted)
leading-tokens-strippedinput, removed, outputLeading tokens (for example env, command) removed before analysis
shell-wrapperwrapper, innerCommandA shell wrapper (bash -c, etc.) was unwrapped
interpreterinterpreter, codeArg, paranoidBlockedAn interpreter one-liner was inspected; paranoidBlocked indicates paranoid mode denied it outright
busyboxsubcommandA busybox-style dispatch was resolved to a subcommand
recursereason, innerCommand, depthRecursive re-analysis triggered by a wrapper, interpreter, or busybox dispatch
rule-checkruleModule, ruleFunction, matched, reason?A built-in rule module was evaluated
worktree-relaxationoriginalReason, gitCwdA git discard command was relaxed because the target is a linked worktree
tmpdir-checktmpdirValue, isOverriddenToNonTemp, allowTmpdirVar$TMPDIR resolution and override detection
fallback-scantokensScanned, embeddedCommandFound?Fallback dangerous-text scan over remaining tokens
custom-rules-checkrulesChecked, matched, reason?User-defined rules were evaluated
cwd-changesegment, effectiveCwdNowUnknownA cd/pushd changed the effective cwd; subsequent classification uses the new (or unknown) cwd
dangerous-texttoken, matched, reason?A token was scanned against dangerous text patterns
strict-unparseablerawCommand, reasonStrict mode failed-closed on an unparseable command
segment-skippedindex, reasonA segment was skipped because a prior segment already blocked
errormessage, partial?An analysis error was captured; partial indicates partial output

Reading a trace

A typical trace flows from parse → per-segment env-strip / leading-tokens-stripped → detection (shell-wrapper / interpreter / busybox) → rule-check (or custom-rules-check) → a decision. Recursion appears as recurse steps with increasing depth. When you only need the verdict, read result (and reason / segment) at the top level instead of walking the trace.
Secret values in trace output are redacted — KEY=value appears as KEY=<redacted> — so traces are safe to share in bug reports. See the Audit Log reference for the redaction system.
Last modified on June 22, 2026