Analyses an Elixir/OTP project's supervision structure and the runtime coupling between processes, reporting where the supervision tree understates the real failure topology.
Firebreak reads the supervision tree the same way OTP does — by calling each
supervisor's init/1 — whenever the project is compiled (it compiles the
current project first for you). It never starts your supervision tree; init/1
only returns child specs, it doesn't run them. For code it can't load it
falls back to static source parsing, and the coupling graph is always static.
mix firebreak # analyse the current project, text report
mix firebreak ../other_app # analyse a project at another path
mix firebreak --format json # machine-readable output (CI artifact)
mix firebreak --format dot # Graphviz graph (pipe to `dot -Tsvg`)
mix firebreak --format mermaid # Mermaid graph (paste into a Markdown doc)
mix firebreak --min-severity medium
mix firebreak --fail-on high # exit non-zero if any HIGH finding (CI gate)
mix firebreak --path "lib/**/*.ex" # restrict source globs (repeatable)
mix firebreak --no-compile # skip compilation; analyse statically
mix firebreak --observe app@host # fold in a live node's real runtime shape
mix firebreak --write-baseline .firebreak_baseline.exs # snapshot current findings
mix firebreak --baseline .firebreak_baseline.exs --fail-on info # gate on regressions onlyOptions
--format(-f) —text(default),json,dot,mermaid,github(PR annotations),html,model(the supervision-model IR; seemix firebreak.specfor TLA+/Quint generation),score(a structural supervision-risk score + per-supervisor ranking, for dashboards/trend tracking),failure(a Mermaid diagram of the cross-tree failure modes — who blocks on:noprocwhen a process in another subtree restarts), oroverlay(the static IR's synchronous crossings annotated with a live node's observed state — target alive?, mailbox depth, instance count; requires--observe, seeFirebreak.RuntimeOverlay)--all— show every finding (default text output collapses the low/info structural & advisory findings to a count for a high-signal first read)--min-severity— hide findings below this severity (high|medium|low|info)--fail-on— exit 1 if any finding is at or above this severity--path— source glob to scan (repeatable; defaults to lib/ + umbrella apps)--no-compile— don't compile first; rely on static parsing only--observe— attach to a live node (name@host) and fold in its real runtime shape: live (incl.DynamicSupervisor) children, recovered registered names, andruntime_fanoutcardinality findings (seeFirebreak.Observe)--cookie— distribution cookie for--observe(if not the default)--config— suppression config (defaults to.firebreak.exsin the project root)--baseline— only report findings absent from this baseline file (regression gate)--write-baseline— write the current findings as a baseline and exit without failing--write-expected— snapshot the current supervision topology to a conformance spec file (commit it), without failing the run--expect— diff the current topology against a committed spec and reporttopology_driftfindings (strategy flips, dropped children, intensity changes)
CI gating
Commit a .firebreak.exs allowlist for findings you've accepted, and/or
snapshot a baseline so the pipeline fails only on new coupling:
mix firebreak --write-baseline .firebreak_baseline.exs # once, on a green commit
mix firebreak --baseline .firebreak_baseline.exs --fail-on info # in CI thereafterSee Firebreak.Baseline for the .firebreak.exs format.