# Share a Clinic.js Report — Doctor, Flame and Bubbleprof as Links

Canonical: https://commareports.com/share-clinicjs-report
Published: 2026-09-08

> clinic doctor writes an HTML report that only opens on the machine that made it. Publish it to Comma for a URL your team can open, and comment on the event-loop stall.

# Share a Clinic.js report

Clinic.js is three tools and they answer three different questions:

```bash
clinic doctor     --dest .clinic -- node app.js   # what kind of problem is this?
clinic flame      --dest .clinic -- node app.js   # which function is burning CPU?
clinic bubbleprof --dest .clinic -- node app.js   # where is the async time going?
```

`doctor` is the one to run first, because it classifies: event loop blocked,
I/O bound, garbage collection, or genuinely CPU bound. Its recommendation panel
is the most useful paragraph in Node performance tooling, and it is the part
that gets flattened when the report becomes a screenshot.

The reports are HTML, and they are stubbornly local. Depending on the tool and
version, the page pulls parts of its dataset at load time — and a browser blocks
those fetches from a `file://` origin. So a colleague who double-clicks the file
you sent gets a page that renders, and charts that never populate.

## Publish it

Point Clinic at a known directory and publish the folder:

```bash
clinic doctor --dest .clinic --autocannon [ -c 100 -d 30 http://localhost:3000/ ] \
  -- node app.js
```

Drag `.clinic/` (or a zip of it) into [the app](https://commareports.com/):

- The generated `*.html` becomes the **report body**.
- The data directory beside it uploads as assets and its relative references
  are rewritten to the uploaded copies — which is the step `file://` cannot do.
- Scripts run inside a sandboxed iframe (`allow-scripts`, no
  `allow-same-origin`), so the charts, the brush-to-zoom on the timeline, and
  the recommendation panel all work.

## Publish the verdict and the follow-up together

A `flame` report on its own is a picture of some functions. A `doctor` report
that says "the event loop is blocked" followed by the `flame` graph showing
`crypto.pbkdf2Sync` at the top is a diagnosis anybody can follow.

PATCH both to one report id:

```bash
curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html "$(ls -t .clinic/*.html | head -1)" \
        --arg t "Clinic flame — /login, sync hashing" '{title: $t, html: $html}')"
```

One URL, a revision per capture. The revision list is the investigation.

## From CI

Event-loop regressions are invisible until latency alarms fire. Run a fixed
load in the job:

```bash
clinic doctor --dest .clinic --autocannon [ -c 50 -d 20 http://localhost:3000/api ] \
  -- node server.js
```

then PATCH the HTML to the same report id every run. A stable URL per service
turns "is p99 creeping?" into a comparison rather than a hunch.

## What review adds

- **Anchored threads** on the stall — see [commenting on HTML](/comment-on-html).
- **Revisions**, so a fix is verifiable against the run that motivated it.
- **Access per report** — private, team, domain-gated or named reviewers. See
  the [sharing model](/docs/sharing).

## Limits

- **Entry HTML: 5 MB.** Assets: 25 MB per file, 250 MB and 500 files total.
  Clinic's data directory is the part that grows with capture length — a 20-30
  second load run is the right size for something meant to be read.
- **60 requests/minute per token.**

## Try it

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

**[Publish a Node profile →](https://commareports.com/)**

### Related

- [Share an autocannon report](/share-autocannon-report) · [Share a flame graph](/share-flamegraph)
- [Share a speedscope profile](/share-speedscope-profile) · [Share a k6 load test report](/share-k6-load-test-report)
- [Share a profiling report](/share-profiling-report) · [Share an HTML folder](/share-html-folder)
