Agents CLI: let AI coding agents fix Rust performance regressions
hotpath cloud is the command line client of the hotpath Cloud API. It gives a coding agent, a script or a CI step the same judgement the pull request comment shows, as JSON: which report was compared with which baseline, under which policy, what regressed, which budgets broke, and the verdict. An agent can push a change, wait for the benchmark, read the verdict and fix what regressed, without opening the dashboard.
Give your agent the hotpath_cloud agent skill: it teaches the agent how to use these commands, wait for a benchmark, read the verdict and fix what regressed.
Install and authenticate
cargo install hotpath --features cloud
Create a personal API token at hotpath.rs/app/tokens and export it:
export HOTPATH_API_TOKEN=...
hotpath cloud auth --pretty
{
"login": "pawurb",
"token": {
"name": "laptop",
"expires_at": "2026-12-25T11:27:12.311073Z"
}
}
The token gives the CLI access to the same repositories as your account on hotpath.rs: the ones your GitHub user can see that have the hotpath GitHub App installed. They are listed on hotpath.rs/app, where you can also add more.
CLI commands
repos and benchmarks
repos lists every repository the token reaches, with its benchmarks. benchmarks lists one repository’s:
hotpath cloud benchmarks --repo pawurb/hotpath-rs --pretty
{
"repository": "pawurb/hotpath-rs",
"benchmarks": [
{ "name": "drain", "reports": 55, "latest_report_at": "2026-10-01T23:09:00.46559Z" },
{ "name": "meta", "reports": 54, "latest_report_at": "2026-10-01T23:09:29.367532Z" }
]
}
report
Fetches one stored report, selected by pull request, commit or id:
hotpath cloud report --repo pawurb/hotpath-rs --benchmark drain --pr 604 --no-payload --pretty
{
"id": "01a0f476-5b3a-7d0e-901a-7756f28e2414",
"event": "pull_request",
"commit_sha": "ac5d8dcb4d21b714e0d2a04fd837637b3e1d1356",
"head_ref": "perf/cycle-drain-buffer",
"pr_number": 604,
"baseline_id": "01a0f43f-c0f8-71c0-bfcc-ef82bbb17270",
"comment_url": "https://github.com/pawurb/hotpath-rs/pull/604#issuecomment-5783640286",
"regressed": false,
"policy_path": "hotpath/drain-policy.toml",
"dashboard_url": "https://hotpath.rs/app/repos/pawurb/hotpath-rs/benchmarks/drain/reports/01a0f476-5b3a-7d0e-901a-7756f28e2414"
}
| Flag | Selects |
|---|---|
--pr N | the newest report of the pull request |
--commit SHA | the newest report of a full 40-character commit sha, measured or as the pull request’s head |
--id ID | the report with this id |
--event push|pull_request | narrows --pr or --commit to one event |
--commit $(git rev-parse HEAD) works on a pull request branch: CI measures GitHub’s merge commit, and the report also matches the pull request’s head commit. Without --no-payload the answer also carries the full uploaded hotpath report.
A report that is not there yet answers not_found with exit code 1, so polling report until it exits 0 waits for CI’s upload.
diff
Compares a report with its baseline under the policy the report carried, exactly as the pull request comment did. It selects the report with the same flags as report:
hotpath cloud diff --repo pawurb/hotpath-rs --benchmark drain --pr 604 --pretty
Trimmed answer:
{
"rows": "findings",
"verdict": {
"judged": true,
"regressed": false,
"regressions": 0,
"improvements": 1,
"budgets_broken": 0
},
"budgets": { "rules": 1, "broken": 0, "findings": [], "notes": [] },
"result": {
"status": "compared",
"sections": [
{
"resource": "functions",
"kind": "alloc",
"family": { "name": "alloc", "judged": true, "min_percent_change": 2.0, "metrics": ["avg", "total"] },
"rows": [
{
"name": "hotpath_drain::EventProducer::push",
"location": { "file": "crates/hotpath-drain/src/lib.rs", "line": 194 },
"outcome": "improvement",
"cells": [
{ "column": "avg", "unit": "bytes", "base": "24 B", "head": "1 B", "change_percent": -95.83, "crossed": "down" },
{ "column": "total", "unit": "bytes", "base": "23.1 MB", "head": "1.2 MB", "change_percent": -94.98, "crossed": "down" }
]
}
]
}
]
},
"dashboard_url": "https://hotpath.rs/app/repos/pawurb/hotpath-rs/benchmarks/drain/reports/01a0f476-5b3a-7d0e-901a-7756f28e2414/diff"
}
How to read it:
verdictcovers the comparison and the budgets together.judgedsays whether anything was judged,regressedwhether a judged section regressed or a budget broke.result.statusiscompared,no_baselineorunreadable. Budgets are checked without a baseline too.- Each section is one section of the regression policy. A row’s
outcomeisregression,improvement,addedorremoved, and itscellsare the values that explain it. A cell withcrossedwent past the policy’smin_percent_change,upordown. - Values are strings formatted as the comment shows them, with their
unit.change_percentis the exact number to reason about. budgets.findingslists the broken budget checks, each with its entry,actual,limitand the rule’smessage.
By default the answer lists only what the comment lists. --advisory adds the findings of sections the policy lists with judged = false, which never count toward the verdict. --full lists every row and every value.
diff exits 0 only when the report was judged and nothing regressed. A regression, a broken budget, or nothing to judge (no baseline and no budgets) exits 1 with the answer on stdout.
validate-policy and init
init writes the default policy to hotpath/policy.toml, and validate-policy checks a policy file before you push it. See regression policy.
hotpath cloud init
hotpath cloud validate-policy --pretty
Output and exit codes
Every command prints one JSON document on stdout, compact by default, indented with --pretty, or written to a file with --output FILE. An error prints one JSON document on stderr and nothing on stdout:
{"error":"No report for PR #999999 in benchmark drain.","code":"not_found"}
| Exit code | Meaning |
|---|---|
0 | success; for diff, the report was judged and nothing regressed |
1 | an error (not found, auth, network, invalid argument value), or for diff any answer that is not “judged and fine” |
2 | usage error |