# Share a SHAP Plot — Model Explanations a Reviewer Can Open

Canonical: https://commareports.com/share-shap-plot
Published: 2026-08-25

> shap.save_html writes an interactive force plot that only opens on your machine. Publish it to Comma: a link the risk reviewer or product owner can open, with comments on the feature they're questioning.

# Share a SHAP plot

Model explanation has an audience problem. The person who most needs to
see which features drove a prediction — a risk reviewer, a clinician, a
product owner, the domain expert who will spot the leaked feature — is
the person least likely to open a notebook.

So the explanation gets screenshotted into a deck, and the interactive
part, which is the part that answers follow-up questions, is gone.

## Publish the interactive plot

```python
import shap

explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test)

shap.save_html("shap.html", shap.force_plot(explainer.expected_value, shap_values, X_test))
```

```bash
curl -X POST https://commareports.com/api/v1/reports \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html shap.html \
        '{title: "Churn model v4 — SHAP", html: $html, visibility: "registered"}')"
```

Or drag `shap.html` into [the app](https://commareports.com/). The
plot's JavaScript runs inside a sandboxed iframe (`allow-scripts`, no
`allow-same-origin`), so hovering, reordering and the sample selector
work at the link — see
[interactive HTML reports](/interactive-html-reports).

## The static plots, with the argument around them

Summary, beeswarm, waterfall and dependence plots are matplotlib
figures. Save them and wrap them in the page you'd otherwise have
written in Slack:

```python
import base64, io, matplotlib.pyplot as plt

shap.summary_plot(shap_values, X_test, show=False)
buf = io.BytesIO(); plt.savefig(buf, format="png", bbox_inches="tight", dpi=144)
img = base64.b64encode(buf.getvalue()).decode()

html = f"""
<h1>Churn model v4 — what drives the score</h1>
<p><code>days_since_last_login</code> dominates, as expected.
<code>support_tickets_30d</code> is third, which is new in v4 and worth a look.</p>
<img src="data:image/png;base64,{img}" alt="SHAP summary plot">
"""
```

One report holding the plots and the interpretation is a better review
artifact than either alone.

## Why the link matters for model review

- **Anchored threads** on the feature someone distrusts — the leak, the
  proxy variable, the one that shouldn't be predictive. See
  [commenting on HTML](/comment-on-html).
- **Revisions per model version**, so v5's explanation sits at the same
  URL as v4's and the two can be diffed.
- **Access control** — private, team, domain-gated or named reviewers,
  which matters when the features are customer attributes. See the
  [sharing model](/docs/sharing).
- **A record of the sign-off**, which is what a model-risk process asks
  for and a notebook cell can't hold.

## Limits

- **Entry HTML: 5 MB.** A force plot over thousands of rows inlines all
  of them — sample first (`X_test.sample(500)`), which is also the more
  readable plot.
- **60 requests/minute per token.**

## Try it

Comma is free — unlimited reports, unlimited commenters, unlimited
revision history.

**[Publish a model report →](https://commareports.com/)**

### Related

- [Share an LLM eval report](/agents/share-llm-eval-report) · [Share an Evidently drift report](/share-evidently-report)
- [Share an EDA report](/share-eda-report) · [Share a Jupyter notebook as HTML](/share-jupyter-notebook-html)
- [Interactive HTML reports](/interactive-html-reports)
