Share a ClearML experiment
ClearML is often chosen precisely because it can be self-hosted: the server runs in your VPC, the data never leaves, and the compliance conversation is short.
That same property is why nobody can see your results. http://clearml.internal:8080/projects/…
is a perfect link on the VPN and a connection timeout everywhere else.
Self-hosting is the feature and the problem
The people who need to see a model's results are rarely all on the network:
- A product owner working from a laptop with no VPN client.
- An external reviewer or auditor.
- A collaborator at a partner org.
- Your own team, on a phone, in a meeting room.
Handing them a VPN and a ClearML account to see one metrics table is a disproportionate ask, and the usual fallback — screenshotting the scalars tab into Slack — throws away every number's precision. See stop screenshotting reports.
Pull the results, publish the page
The SDK gives you everything the UI shows:
from clearml import Task
task = Task.get_task(task_id=task_id)
scalars = task.get_last_scalar_metrics()
params = task.get_parameters()
# render a page from scalars, params and the plots you care about, then publish
Publish one document containing the comparison against the incumbent, the two or three plots that carry the argument, the parameter set, and the task id for anyone who is on the VPN and wants the raw run.
The task id in the footer matters: it keeps the internal system of record authoritative while letting the conclusion travel.
You choose what crosses the boundary
The objection to any external publishing in a self-hosted shop is, correctly, "what leaves?"
The answer here is: exactly the fields you put in the page. A metrics table, rendered plots, hyperparameters. Not the dataset, not the model weights, not the artifacts. And the report itself can be access-restricted rather than open — see security and the subprocessor list if procurement asks.
Automate it at the end of the task
task = Task.init(project_name="churn", task_name="v31")
...
publish_report(title=f"churn · {task.name}", html=render(task))
Every completed run refreshes the same report id, so the link in your tracking ticket always shows the current state, with the previous round's comments still attached. If the schedule is the hard part, routines can own it.
Worth knowing
- Static plots, not iframes. Embedding the internal UI produces a page that fails for exactly the audience you built it for.
- Publish numbers as text, not pictures. A screenshotted metrics table cannot be searched, copied or diffed.
- Comments anchor to the figure — see commenting on HTML.
- 5 MB per report body.
Try it
Free — unlimited reports, commenters and revisions.