Skip to main content
explain --json returns the decision for a command plus a trace of each analysis step, as one JSON object. Scripts read the decision from the top-level fields and walk the trace for detail. For flags and exit codes, see explain.
A trace is not automatically safe to share. Read Before you share a trace first.

ExplainResult

effectiveCapabilities

effectiveCapabilities is a record keyed by fail_closed, paranoid_rm, and paranoid_interpreters. Each value contains: See Modes for what each capability changes.

ruleActivation

ruleActivation is present only when a capability gates the relevant rule. The relevant rule is the matched rule, or a rule that would match if its level or capability were on. Human-readable output shows it as one line: .

ExplainTrace

Recording a trace never changes the decision. CC Safety Net caps very long traces. It shortens long text values and drops steps past the limit.

TraceStep variants

Use type to select the variant before you read its other fields. See Temp-root relaxation for when temp-root-relaxation applies.

recurse reasons

recurse.reason has one of eight values: shell-wrapper, interpreter, busybox, shell-eval, shell-trap, shell-stdin, shell-heredoc, or heredoc-file. heredoc-file means the command ran a script that an earlier heredoc in the same command wrote. See What the analyzer sees through.

script-file steps

A script-file step appears for a command such as sh deploy.sh or ./deploy.sh. path is the path as the command spelled it, and bytes is the file’s size. The commands inside the script produce no further steps, and no field carries the script’s text. See Scripts run from a file. A script that a heredoc in the same command wrote records a recurse step with the reason heredoc-file instead. That step carries the body.

transparent-wrapper steps

A transparent-wrapper step appears when analysis looks through a command registered with rule wrapper add. wrapper is the wrapper name, and output is the token list of the wrapped command. One step per candidate comes right before that command’s analysis.

Trace order

A typical trace starts with parse. Each segment then shows env-strip or leading-tokens-stripped, then the wrapper detection steps shell-wrapper, interpreter, busybox, and transparent-wrapper, then rule-check or custom-rules-check. Nested commands appear as recurse steps with a depth. Four protections block before the evaluator runs. Their trace holds a single synthetic rule-check step and no parse step, so a script that expects every trace to open with parse must handle them:

Before you share a trace

Redaction removes only recognized credential shapes, using the same pattern list as the audit log. File paths, hostnames, IP addresses, usernames, project or client names, and secrets in unrecognized formats stay in full. Reproduce the case with placeholder credentials and paths, then read the output end to end before you share it.
The parse step records the raw command string and every parsed token. These fields also carry raw text:
  • fallback-scan.tokensScanned, dangerous-text.token, strict-unparseable.rawCommand
  • shell-wrapper.innerCommand, interpreter.codeArg, recurse.innerCommand, transparent-wrapper.output
  • script-file.path, worktree-relaxation.gitCwd, temp-root-relaxation.gitCwd, cwd-change.segment
configSource is an absolute path, normally inside your home directory. You can include explain output in a vulnerability report. A credential format that redaction misses in text you supplied is an ordinary bug for a public GitHub issue, not a vulnerability.
Last modified on October 27, 2026