Skip to main content
The explain --json command returns a structured trace of command analysis. This page defines the JSON shape for scripts and other tools. It also explains what a trace can reveal before you share it. See CLI commands for flags and exit behavior. See Troubleshooting for help with an unexpected block.
A trace is not automatically safe to share. Read Before you share a trace first.

ExplainResult

The top-level object returned by explain --json. The result builds effectiveLevel, selectedPreset, effectiveCapabilities, and destructiveCommandRuleOverrides once and includes them in every return path. They are present even when you explain an empty command. safetyPresetScope joins them on the same path, but only when a project .cc-safety-net/policy.json was read. Human output renders the preset in the CONFIG section as , where the scope is user policy, project policy, or built-in default. Without a project policy file the line is with no parenthetical.

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 the relevant rule declares an activation capability. The relevant rule is either the matched rule or a mode-gated candidate. A mode-gated candidate is a rule that would match if its required level or capability were active. Human output renders this as one line: .

ExplainTrace

The trace is passive: recording it never changes a decision, and ordinary guard evaluation never builds one. It exists only for explain. Bounds. The recorder keeps at most 512 events, 2,048 characters per text value, 128 items per list, 128 properties per object, and 16 levels of nesting. It discards events beyond the cap and deep-freezes each recorded value. ExplainTrace exposes only steps and segments.

TraceStep variants

Use type to select the variant before you read its other fields. Human output renders temp-root-relaxation as a numbered Temp-root relaxation step showing Git cwd: and Result: Allowed git discard in a temp-root repository. See Temp-root relaxation for the conditions behind it, and Working-directory tracking for what makes a cd record a cwd-change step.

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 is recorded when a command runs a script file whose content the analysis already knows. The content is a quoted heredoc body written to that path earlier in the same command through cat > or tee. The analyzer then treats the stored body as the script. See Heredoc analysis.

transparent-wrapper steps

transparent-wrapper is a segment-scoped step recorded when the analyzer looks through a command registered with rule wrapper add. It emits one step for the primary child and one for each alternative. Each step carries: The step is recorded immediately before recursing into those tokens, so it always precedes the analysis of the wrapped command. Human output renders it as a numbered Transparent wrapper step showing Wrapper: and Tokens:. Manage wrappers with the rule wrapper add, rule wrapper remove, and rule wrapper list commands. See rule wrapper.

Trace order

A typical trace flows from parse → per-segment env-strip / leading-tokens-stripped → detection (shell-wrapper / interpreter / busybox / transparent-wrapper) → rule-check or custom-rules-check → a decision. Recursion appears as recurse steps with increasing depth, except busybox dispatch, which records a recurse step but does not consume recursion depth, so a chain of busybox wrappers repeats the same depth value. When you only need the verdict, read result (plus reason, segment, and ruleId) at the top level instead of walking the trace. Three protections short-circuit before the evaluator runs: policy-file protection, Git-metadata protection, and secret protection. When one of those blocks a command, the trace contains a single synthetic rule-check step and no parse step, with ruleId set to policy-protection, git-metadata-protection, or the id of the matched secret rule. Tooling that assumes every trace opens with a parse step needs to handle this case.

Before you share a trace

An explain trace is not inherently safe to share. The parse step records the raw command string and every parsed token. Other fields also carry raw text: fallback-scan.tokensScanned, dangerous-text.token, shell-wrapper.innerCommand, interpreter.codeArg, recurse.innerCommand, strict-unparseable.rawCommand, transparent-wrapper.output, worktree-relaxation.gitCwd, temp-root-relaxation.gitCwd, and cwd-change.segment. configSource is an absolute path, normally inside your home directory.Redaction removes only recognized credential shapes from the bounded pattern list used by the audit log. It does not cover file paths, hostnames, IP addresses, usernames, project or client names, or secrets with unrecognized formats.Before sharing a trace: reproduce the case with placeholder credentials and placeholder paths, then read the output end to end and remove anything you would not post publicly.
For example, explaining a command that contains a --token=… assignment redacts the token, but a path like /srv/acme-prod/customer-dump.sql in the same command is returned in full, along with any hostname, IP address, or account name in the command text. You can include explain output in a vulnerability report. Redaction is a best-effort control, not a guarantee. A redaction bypass is a reportable vulnerability. Review the complete output before you paste it.
  • CLI commands documents explain flags, examples, and exit behavior.
  • Audit log lists the redaction patterns and applies the same bound to logged records.
  • Analysis engine defines the behavior behind each trace step.
  • Troubleshooting explains how to use explain for an unexpected block.
Last modified on September 21, 2026