Scalus Profile — VS Code extension
Annotate your Scala source with Scalus CEK-machine
profiling cost, right in the editor, and open the full interactive profile report in a panel.
When you profile a Scalus smart contract, the evaluator emits a machine-readable
profile.json (per-source-location and per-builtin cost, the control-flow edges, and the total
budget). This extension reads that file and shows the cost inline on the source lines that
produced it.

Features
- Inline cost annotations — each profiled line gets
⏱ <cpu> · <mem> · <count>× · <fee> lov
at the end of the line.
- Heat background — lines are tinted by their share of the selected metric (cpu or fee), so
hot spots jump out.
- Hover breakdown — hover a profiled line for its totals, the builtins invoked there, and the
hottest control-flow edges leaving it.
- Status bar — total CEK budget and on-chain fee; click to open the full report.
- Open Report — loads the self-contained interactive HTML report (sortable tables, hot paths,
annotated source) into a webview.
- Compiled UPLC view – opens the compiled Untyped Plutus Core of the profiled run beside your
code, syntax-highlighted, with the cursor synced in both directions.
- Auto-refresh — re-reads the profile when your tests regenerate it.
Producing a profile
From a Scalus project, run an evaluation with profiling enabled. The simplest way is the
environment switch:
SCALUS_PROFILE=full <your test/run command>
For every profiled script run this writes, into the report output directory (SCALUS_DUMP_DIR,
default: target/scalus):
<scriptHash>-<tag>-<index>.profile.html – the interactive report
<scriptHash>-<tag>-<index>.profile.json – machine-readable data ("schemaVersion": 1)
<scriptHash>-<tag>-<index>.profile.csv – flat table
profile-manifest.json – the discovery entry point listing every run
The extension reads profile-manifest.json first (schema version 1, checked): each run appears
in the profile picker labelled by script hash, redeemer and Plutus version, and "Open Report"
opens the HTML report belonging to the selected run. Without a manifest (older Scalus), the
extension falls back to scanning for *profile*.json files, newest first – e.g. ones written
directly with:
ProfileFormatter.writeJson(profile, "target/my-profile.json")
ProfileFormatter.writeHtml(profile, "target/my-profile.html") // optional, for the report panel
The JSON file paths are absolute source paths captured at compile time; the extension matches
them to your open files by trailing path segments, so a profile generated on CI still lines up.
Usage
- Open your Scalus project folder in VS Code.
- Generate a profile (above). The extension auto-discovers it via
profile-manifest.json
(or the newest *profile*.json when there is no manifest).
- Open a profiled
.scala file — annotations appear on the costed lines.
- Run Scalus Profile: Open Report from the Command Palette for the rich view.
Commands
| Command |
Description |
Scalus Profile: Open Report |
Open the HTML report in a webview |
Scalus Profile: Show Compiled UPLC |
Open the compiled UPLC of the selected run beside the editor |
Scalus Profile: Show Compiled UPLC for Function |
Highlight all UPLC compiled from the function at the cursor |
Scalus Profile: Reload Profile Data |
Re-read the profile JSON |
Scalus Profile: Toggle Inline Annotations |
Show/hide inline cost text |
Scalus Profile: Select Profile File |
Pick among the manifest's profile runs (or loose profile.json files) |
Settings
| Setting |
Default |
Description |
scalusProfile.manifestGlob |
**/profile-manifest.json |
Where to find the profile manifest (source of truth when present) |
scalusProfile.jsonGlob |
**/*profile*.json |
Fallback: where to find the profile JSON (newest wins) |
scalusProfile.htmlGlob |
**/*profile*.html |
Where to find the HTML report |
scalusProfile.metric |
cpu |
Primary metric: cpu or fee (fee falls back to cpu when unpriced) |
scalusProfile.showInline |
true |
Inline per-line annotations |
scalusProfile.showHeat |
true |
Line heat backgrounds |
scalusProfile.minPercent |
0 |
Only annotate lines ≥ this % of the file's hottest line |
scalusProfile.heatColor |
220,40,40 |
Base RGB for the heat tint |
Compiled UPLC view
Scalus compiles your Scala to Untyped Plutus Core, and that is what the CEK machine actually
runs. Alongside the profile files, Scalus writes a UPLC source map,
<scriptHash>-<tag>-<index>.uplc.json: the pretty-printed program plus, for every printed node,
the Scala source range it came from. The extension opens that program in a read-only editor
beside your code.
| Command |
What it does |
Scalus Profile: Show Compiled UPLC |
Opens the compiled UPLC of the selected profile run beside the active editor |
Scalus Profile: Show Compiled UPLC for Function |
Highlights every UPLC region compiled from the function at the cursor, and reveals the first one |
Cursor sync works in both directions once the UPLC editor is open:
- Move the cursor in a
.scala file – every UPLC node compiled from that position is
highlighted, and the innermost one is revealed.
- Move the cursor in the UPLC editor – the Scala range that produced the node under the cursor is
highlighted and revealed. The Scala file must already be visible; the view does not open files
for you.
Show Compiled UPLC for Function resolves the function from either editor. One function usually
compiles to several stretches of UPLC, so the command highlights all of them, merged into
contiguous regions and restricted to the file the cursor is in – same-named functions in other
files are not painted.
The UPLC text is registered as its own language (uplc) with a syntax grammar, so keywords,
builtin names, constant types and literals are coloured. Files with a .uplc extension get the
same highlighting.
Requirements. The view needs the UPLC source map, which only recent Scalus versions write:
- Profile at level full (
SCALUS_PROFILE=full), and let the run render report files.
Console-only profiling writes nothing to disk, so there is no source map either.
- The run's entry in
profile-manifest.json must list a file of format "uplc". With an older
Scalus the profile still works and the command reports that no UPLC map is available.
Development
npm install
npm run compile # bundle to dist/extension.js (esbuild)
npm run typecheck # tsc --noEmit
npm run vsce:package # build a .vsix
Press F5 in VS Code to launch the Extension Development Host. Open the
fixtures/ folder (or any Scalus project) — fixtures/sample-profile.json and
sample-profile.html are real output from the Scalus auction example, so you can see the
annotations and report immediately.
License
Apache-2.0