Perf Lens — API

Paste the code, get a senior performance review and an optimized rewrite.

API tokens Open the app

Review code for performance from your own scripts

Send code — a module, a component, a request handler, a query layer, or a mixed grab-bag — and get back one JSON object: an honest verdict, a health check across five performance areas, findings ranked by severity each with a corrected snippet, the quick wins worth shipping first, and an optimized rewrite of the worst hotspot. Everything this app does goes through the SkillSafe App API — plain JSON over HTTPS — so you can wire review into a CI gate, a pull-request bot, or a pre-deploy check that refuses to ship an await inside a loop. Every code step below is shown in cURL, Python, JavaScript, Go, Java, Ruby, PHP and C#; pick a language once and the whole page follows.

Basics

Base URL: https://api.skillsafe.ai/v1/app-api, app slug perf-lens. Every request sends Authorization: Bearer <token> and JSON bodies with Content-Type: application/json. Responses are wrapped in an envelope: {"data": …} on success, {"error": {"code", "message"}} on failure. The review itself is produced by the gpt-terra model. Estimates are free; runs are metered against your credit balance. There is a single run task — one paste in, one review out, no follow-up calls and no session state to carry.

StatusMeaning
401Missing or expired token — create a new session.
402Not enough credits — top up at skillsafe.ai/account/credits.
403The token isn't allowed to do this (e.g. a guest reviewing a very large paste).
404Unknown job or record id.
5xxTransient platform error — retry with backoff.

Browsers enforce CORS for this API, so run these examples from a server, script or terminal — not from another website's frontend.

Step 0 — A tiny client

Every task below is a single HTTP call, so start with a short helper that adds the auth header, sends JSON and unwraps the data envelope. The later steps reuse it.

export API="https://api.skillsafe.ai/v1/app-api"
export TOKEN="YOUR_TOKEN"      # see step 1

# every call looks like:
#   curl -s "$API/..." -H "Authorization: Bearer $TOKEN" [-d '{json}']
# jq is used below to pull fields out of the {"data": ...} envelope
import json, requests

API = "https://api.skillsafe.ai/v1/app-api"
TOKEN = "YOUR_TOKEN"  # see step 1 — read it from your shell environment in real code

def api(method, path, body=None, **headers):
    res = requests.request(method, API + path, json=body,
                           headers={"Authorization": f"Bearer {TOKEN}", **headers})
    payload = res.json()
    if not res.ok:
        raise RuntimeError(payload.get("error", {}).get("message", res.reason))
    return payload["data"]
// Node 18+ (built-in fetch)
const API = "https://api.skillsafe.ai/v1/app-api";
const TOKEN = "YOUR_TOKEN"; // see step 1 — read it from your shell environment in real code

async function api(method, path, body, extraHeaders = {}) {
  const res = await fetch(API + path, {
    method,
    headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json", ...extraHeaders },
    body: body === undefined ? undefined : JSON.stringify(body),
  });
  const json = await res.json();
  if (!res.ok) throw new Error(json.error?.message ?? res.statusText);
  return json.data;
}
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
)

const API = "https://api.skillsafe.ai/v1/app-api"

var token = os.Getenv("SKILLSAFE_TOKEN") // see step 1

func call(method, path string, body, out any) error {
	var buf bytes.Buffer
	if body != nil {
		json.NewEncoder(&buf).Encode(body)
	}
	req, _ := http.NewRequest(method, API+path, &buf)
	req.Header.Set("Authorization", "Bearer "+token)
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	var env struct {
		Data  json.RawMessage `json:"data"`
		Error *struct{ Message string `json:"message"` } `json:"error"`
	}
	json.NewDecoder(res.Body).Decode(&env)
	if res.StatusCode >= 400 {
		return fmt.Errorf("api %s %s: %s", method, path, env.Error.Message)
	}
	if out == nil {
		return nil
	}
	return json.Unmarshal(env.Data, out)
}
// Java 17+, no dependencies. Pair with your JSON library (Jackson, Gson…)
// to read fields out of the returned envelope.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class SkillSafe {
    static final String API = "https://api.skillsafe.ai/v1/app-api";
    static final String TOKEN = System.getenv("SKILLSAFE_TOKEN"); // see step 1
    static final HttpClient HTTP = HttpClient.newHttpClient();

    static String api(String method, String path, String jsonBody) throws Exception {
        var req = HttpRequest.newBuilder(URI.create(API + path))
            .header("Authorization", "Bearer " + TOKEN)
            .header("Content-Type", "application/json")
            .method(method, jsonBody == null
                ? HttpRequest.BodyPublishers.noBody()
                : HttpRequest.BodyPublishers.ofString(jsonBody))
            .build();
        var res = HTTP.send(req, HttpResponse.BodyHandlers.ofString());
        if (res.statusCode() >= 400) throw new RuntimeException(res.body());
        return res.body(); // envelope: {"data": …}
    }
}
require "net/http"
require "json"

API = "https://api.skillsafe.ai/v1/app-api"
TOKEN = ENV.fetch("SKILLSAFE_TOKEN") # see step 1

def api(method, path, body = nil)
  uri = URI(API + path)
  req = Net::HTTP.const_get(method.capitalize).new(uri)
  req["Authorization"] = "Bearer #{TOKEN}"
  req["Content-Type"] = "application/json"
  req.body = body.to_json if body
  res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
  payload = JSON.parse(res.body)
  raise (payload.dig("error", "message") || res.message) unless res.is_a?(Net::HTTPSuccess)
  payload["data"]
end
<?php
const API = "https://api.skillsafe.ai/v1/app-api";
$TOKEN = getenv("SKILLSAFE_TOKEN"); // see step 1

function api(string $method, string $path, ?array $body = null): mixed {
    global $TOKEN;
    $ch = curl_init(API . $path);
    curl_setopt_array($ch, [
        CURLOPT_CUSTOMREQUEST  => $method,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER     => [
            "Authorization: Bearer $TOKEN",
            "Content-Type: application/json",
        ],
        CURLOPT_POSTFIELDS     => $body === null ? null : json_encode($body),
    ]);
    $payload = json_decode(curl_exec($ch), true);
    $status  = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    curl_close($ch);
    if ($status >= 400) {
        throw new Exception($payload["error"]["message"] ?? "HTTP $status");
    }
    return $payload["data"];
}
// .NET 8+
using System.Net.Http.Json;
using System.Text.Json;

static class SkillSafe
{
    const string Api = "https://api.skillsafe.ai/v1/app-api";
    static readonly HttpClient Http = new();

    static SkillSafe() =>
        Http.DefaultRequestHeaders.Authorization =
            new("Bearer", Environment.GetEnvironmentVariable("SKILLSAFE_TOKEN")); // see step 1

    public static async Task<JsonElement> ApiAsync(HttpMethod method, string path, object? body = null)
    {
        var req = new HttpRequestMessage(method, Api + path);
        if (body != null) req.Content = JsonContent.Create(body);
        var res = await Http.SendAsync(req);
        var json = await res.Content.ReadFromJsonAsync<JsonElement>();
        if (!res.IsSuccessStatusCode)
            throw new Exception(json.GetProperty("error").GetProperty("message").GetString());
        return json.GetProperty("data");
    }
}

Step 1 — Get a token

POST /guest

A guest token lets you check balances and estimate costs for free. For metered review runs billed to your own account, use your personal token: open the token page, sign in with SkillSafe, and press Copy shell export — it puts export SKILLSAFE_TOKEN="…" on your clipboard, which every example below reads. Treat the token like a password: it can spend your credits. For fully headless scripts, POST /guest mints a guest token with no browser involved.

curl -s -X POST "$API/guest" \
  -H "Content-Type: application/json" \
  -d '{"slug":"perf-lens"}' | jq -r '.data.token'
token = api("POST", "/guest", {"slug": "perf-lens"})["token"]
const { token } = await api("POST", "/guest", { slug: "perf-lens" });
var guest struct{ Token string `json:"token"` }
err := call("POST", "/guest", map[string]string{"slug": "perf-lens"}, &guest)
String envelope = api("POST", "/guest", """
    {"slug":"perf-lens"}""");
// token is at data.token in the returned JSON
token = api("POST", "/guest", { slug: "perf-lens" })["token"]
$token = api("POST", "/guest", ["slug" => "perf-lens"])["token"];
var guest = await SkillSafe.ApiAsync(HttpMethod.Post, "/guest",
    new { slug = "perf-lens" });
var token = guest.GetProperty("token").GetString();

The app stores this browser's token under the localStorage key skillsafe_app_token:perf-lens, on the app's own origin. The token page reads and manages it for you — you never need to open developer tools.

Step 2 — Check who you are and your balance

GET /me

Returns subject_type ("user" or "guest"), subject_id and your credits balance. Check this before reviewing a large paste.

curl -s "$API/me" -H "Authorization: Bearer $TOKEN" | jq '.data'
me = api("GET", "/me")
print(me["subject_type"], me["credits"])
const me = await api("GET", "/me");
console.log(me.subject_type, me.credits);
var me struct {
	SubjectType string `json:"subject_type"`
	Credits     int64  `json:"credits"`
}
err := call("GET", "/me", nil, &me)
String envelope = api("GET", "/me", null);
// data.subject_type, data.credits
me = api("GET", "/me")
puts "#{me["subject_type"]}: #{me["credits"]} credits"
$me = api("GET", "/me");
echo "{$me['subject_type']}: {$me['credits']} credits\n";
var me = await SkillSafe.ApiAsync(HttpMethod.Get, "/me");
Console.WriteLine($"{me.GetProperty("subject_type")}: {me.GetProperty("credits")} credits");

Step 3 — Estimate the cost

POST /estimate

Send exactly the input you would send to /run; the response's hold_credits is the worst-case cost. Nothing is charged and no job is created, so estimating is free — useful when you are feeding in a whole directory of modules and want a ceiling before spending credits.

Input fieldTypeNotes
codestring, requiredThe source code to review: one file or several concatenated. Very long pastes may be clipped middle-out, with a [... clipped ...] marker showing where.
languagestringauto | javascript | typescript | python | sql | go | java | other. On auto, the language is inferred from the paste and named back to you in the overview.
surfacestringbackend (server handlers, jobs, data access) | frontend (browser and UI rendering) | mixed — calibrates which checklist areas dominate. Rendering findings only make sense for frontend and mixed; connection pooling and N+1 dominate backend.
slowpathstring, optionalWhat you say is slow, verbatim, e.g. "the /report endpoint takes 40s". The review is weighted toward it and says whether the pasted code can explain that symptom.
notesstring, optionalExtra context: data sizes, request rates, framework, environment.
prescan_factsobject, optionalWhat a client-side prescan mechanically detected in the code: {"antipatterns": [], "hotspots": [], "signals": []}. Each entry is {id, label} — pattern-matched anti-pattern hits (ap:await-in-loop), function and component names found in the paste (hotspot:loadOrders) and stack signals (sig:react, sig:sql, sig:node). Every id you send comes back in coverage_check. The web UI fills this from its own scan; API callers may omit the field or send the three empty arrays.
retry_notestring, optionalOnly set by the app's automatic reformat retry when a first reply was not valid JSON. Leave it out.
cat > orders.js <<'JS'
async function loadOrders(userIds) {
  const orders = [];
  for (const id of userIds) {
    const rows = await db.query("SELECT * FROM orders WHERE user_id = $1", [id]);
    orders.push(...rows);
  }
  return orders;
}
JS

jq -n --rawfile c orders.js \
  '{code: $c, language: "javascript", surface: "backend",
    slowpath: "The dashboard takes 8+ seconds for users with many orders.",
    notes: "Node 20 with node-postgres; orders is about 12M rows and loadOrders runs on every dashboard render.",
    prescan_facts: {antipatterns: [], hotspots: [], signals: []}}' > input.json

curl -s -X POST "$API/estimate" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d @input.json | jq '.data.hold_credits'
CODE = """async function loadOrders(userIds) {
  const orders = [];
  for (const id of userIds) {
    const rows = await db.query("SELECT * FROM orders WHERE user_id = $1", [id]);
    orders.push(...rows);
  }
  return orders;
}"""

payload = {
    "code": CODE,
    "language": "javascript",
    "surface": "backend",
    "slowpath": "The dashboard takes 8+ seconds for users with many orders.",
    "notes": "Node 20 with node-postgres; orders is about 12M rows and loadOrders runs on every dashboard render.",
    "prescan_facts": {"antipatterns": [], "hotspots": [], "signals": []},
}

est = api("POST", "/estimate", payload)
print("worst case:", est.get("hold_credits", est.get("credits")), "credits")
const code = `async function loadOrders(userIds) {
  const orders = [];
  for (const id of userIds) {
    const rows = await db.query("SELECT * FROM orders WHERE user_id = $1", [id]);
    orders.push(...rows);
  }
  return orders;
}`;

const payload = {
  code,
  language: "javascript",
  surface: "backend",
  slowpath: "The dashboard takes 8+ seconds for users with many orders.",
  notes: "Node 20 with node-postgres; orders is about 12M rows and loadOrders runs on every dashboard render.",
  prescan_facts: { antipatterns: [], hotspots: [], signals: [] },
};

const est = await api("POST", "/estimate", payload);
console.log("worst case:", est.hold_credits ?? est.credits, "credits");
const code = `async function loadOrders(userIds) {
  const orders = [];
  for (const id of userIds) {
    const rows = await db.query("SELECT * FROM orders WHERE user_id = $1", [id]);
    orders.push(...rows);
  }
  return orders;
}`

payload := map[string]any{
	"code":     code,
	"language": "javascript",
	"surface":  "backend",
	"slowpath": "The dashboard takes 8+ seconds for users with many orders.",
	"notes":    "Node 20 with node-postgres; orders is about 12M rows and loadOrders runs on every dashboard render.",
	"prescan_facts": map[string]any{
		"antipatterns": []any{}, "hotspots": []any{}, "signals": []any{},
	},
}

var est struct{ HoldCredits int64 `json:"hold_credits"` }
err := call("POST", "/estimate", payload, &est)
String code = """
    async function loadOrders(userIds) {
      const orders = [];
      for (const id of userIds) {
        const rows = await db.query("SELECT * FROM orders WHERE user_id = $1", [id]);
        orders.push(...rows);
      }
      return orders;
    }""";

String jsonPayload = """
    {"code": %s, "language": "javascript", "surface": "backend",
     "slowpath": "The dashboard takes 8+ seconds for users with many orders.",
     "notes": "Node 20 with node-postgres; orders is about 12M rows.",
     "prescan_facts": {"antipatterns": [], "hotspots": [], "signals": []}}
    """.formatted(toJsonString(code));

String envelope = api("POST", "/estimate", jsonPayload);
// worst-case cost is at data.hold_credits
CODE_TEXT = <<~JS
  async function loadOrders(userIds) {
    const orders = [];
    for (const id of userIds) {
      const rows = await db.query("SELECT * FROM orders WHERE user_id = $1", [id]);
      orders.push(...rows);
    }
    return orders;
  }
JS

payload = { code: CODE_TEXT, language: "javascript", surface: "backend",
            slowpath: "The dashboard takes 8+ seconds for users with many orders.",
            notes: "Node 20 with node-postgres; orders is about 12M rows.",
            prescan_facts: { antipatterns: [], hotspots: [], signals: [] } }

est = api("POST", "/estimate", payload)
puts "worst case: #{est["hold_credits"] || est["credits"]} credits"
$code = <<<'JS'
async function loadOrders(userIds) {
  const orders = [];
  for (const id of userIds) {
    const rows = await db.query("SELECT * FROM orders WHERE user_id = $1", [id]);
    orders.push(...rows);
  }
  return orders;
}
JS;

$payload = [
    "code"          => $code,
    "language"      => "javascript",
    "surface"       => "backend",
    "slowpath"      => "The dashboard takes 8+ seconds for users with many orders.",
    "notes"         => "Node 20 with node-postgres; orders is about 12M rows.",
    "prescan_facts" => ["antipatterns" => [], "hotspots" => [], "signals" => []],
];

$est = api("POST", "/estimate", $payload);
echo "worst case: " . ($est["hold_credits"] ?? $est["credits"]) . " credits\n";
var code = """
    async function loadOrders(userIds) {
      const orders = [];
      for (const id of userIds) {
        const rows = await db.query("SELECT * FROM orders WHERE user_id = $1", [id]);
        orders.push(...rows);
      }
      return orders;
    }
    """;

var payload = new {
    code,
    language = "javascript",
    surface = "backend",
    slowpath = "The dashboard takes 8+ seconds for users with many orders.",
    notes = "Node 20 with node-postgres; orders is about 12M rows.",
    prescan_facts = new {
        antipatterns = Array.Empty<object>(), hotspots = Array.Empty<object>(),
        signals = Array.Empty<object>(),
    },
};

var est = await SkillSafe.ApiAsync(HttpMethod.Post, "/estimate", payload);
Console.WriteLine($"worst case: {est.GetProperty("hold_credits")} credits");

prescan_facts is how you make the review answer for things you already know about. Send {"antipatterns": [{"id": "ap:await-in-loop", "label": "await inside a loop"}], "hotspots": [{"id": "hotspot:loadOrders", "label": "loadOrders"}], "signals": [{"id": "sig:sql", "label": "SQL queries"}]} and every one of those ids comes back in coverage_check — addressed, or explained away as a false positive. Nothing you flag is silently dropped.

Step 4 — Run the review and wait for the result

POST /run
GET /jobs/{job_id}

/run takes the same input as /estimate, places a credit hold and returns a job_id. Poll /jobs/{job_id} every 1–2 seconds until status is succeeded or failed (a run typically takes 30–90 s, since the optimized rewrite is written out in full). Always send an Idempotency-Key header so a network retry can't start a second, double-charged run. The review is in output — usually nested as output.output, and as a JSON string, so parse defensively. The samples below print the review name and verdict, the five health areas and the findings, then write rewrite.code to optimized.js.

JOB_ID=$(curl -s -X POST "$API/run" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -H "Idempotency-Key: review-$(date +%s)" \
  -d @input.json | jq -r '.data.job_id')

while :; do
  JOB=$(curl -s "$API/jobs/$JOB_ID" -H "Authorization: Bearer $TOKEN")
  STATUS=$(echo "$JOB" | jq -r '.data.status')
  [ "$STATUS" = "succeeded" ] || [ "$STATUS" = "failed" ] && break
  sleep 2
done

# unwrap the review once, then read it
echo "$JOB" | jq -r '.data.output.output' > review.json

jq -r '
  "\(.review_name): \(.verdict)",
  "",
  "HEALTH",
  (.health[] | "  [\(.status)] \(.area) - \(.note)"),
  "",
  "FINDINGS",
  (.findings[] | "  (\(.severity)) \(.category): \(.title)"),
  "",
  "QUICK WINS",
  (.quick_wins[] | "  \(.change)   -- \(.impact)")' review.json

# and drop the optimized rewrite straight into the repo
jq -r '.rewrite.code' review.json > "$(jq -r '.rewrite.filename' review.json)"   # optimized.js
import time

job_id = api("POST", "/run", payload,
             **{"Idempotency-Key": "review-001"})["job_id"]

while True:
    job = api("GET", f"/jobs/{job_id}")
    if job["status"] in ("succeeded", "failed"):
        break
    time.sleep(1.5)

if job["status"] == "failed":
    raise RuntimeError(job.get("error", "run failed"))

raw = job["output"]
if isinstance(raw, dict) and "output" in raw:
    raw = raw["output"]
review = json.loads(raw) if isinstance(raw, str) else raw

print(f'{review["review_name"]}: {review["verdict"]}')
for area in review["health"]:
    print(f'  [{area["status"]:>4}] {area["area"]:<18} {area["note"]}')
for f in review["findings"]:
    print(f'  ({f["severity"]}) {f["category"]}: {f["title"]}')
    if f["fix_code"]:
        print(f'      {f["fix_code"]}')
for w in review["quick_wins"]:
    print(f'  {w["change"]}   -- {w["impact"]}')
for c in review["coverage_check"]:
    print(f'  {c["id"]}: {"ok" if c["addressed"] else "SET ASIDE"} - {c["note"]}')

with open(review["rewrite"]["filename"], "w", encoding="utf-8") as fh:   # optimized.js
    fh.write(review["rewrite"]["code"])
import { writeFileSync } from "node:fs";

const { job_id } = await api("POST", "/run", payload,
  { "Idempotency-Key": crypto.randomUUID() });

let job;
do {
  await new Promise((r) => setTimeout(r, 1500));
  job = await api("GET", `/jobs/${job_id}`);
} while (job.status !== "succeeded" && job.status !== "failed");

if (job.status === "failed") throw new Error(job.error ?? "run failed");

const raw = job.output?.output ?? job.output;
const review = typeof raw === "string" ? JSON.parse(raw) : raw;

console.log(`${review.review_name}: ${review.verdict}`);
for (const area of review.health) {
  console.log(`  [${area.status}] ${area.area}: ${area.note}`);
}
for (const f of review.findings) {
  console.log(`  (${f.severity}) ${f.category}: ${f.title}`);
  if (f.fix_code) console.log(`      ${f.fix_code}`);
}
for (const w of review.quick_wins) console.log(`  ${w.change}   -- ${w.impact}`);
for (const c of review.coverage_check) {
  console.log(`  ${c.id}: ${c.addressed ? "ok" : "SET ASIDE"} - ${c.note}`);
}

writeFileSync(review.rewrite.filename, review.rewrite.code);   // optimized.js
var started struct{ JobID string `json:"job_id"` }
if err := call("POST", "/run", payload, &started); err != nil {
	log.Fatal(err)
}

var job struct {
	Status string          `json:"status"`
	Error  string          `json:"error"`
	Output json.RawMessage `json:"output"`
}
for {
	if err := call("GET", "/jobs/"+started.JobID, nil, &job); err != nil {
		log.Fatal(err)
	}
	if job.Status == "succeeded" || job.Status == "failed" {
		break
	}
	time.Sleep(1500 * time.Millisecond)
}

// job.Output is {"output": "<json string>"} — unwrap, unquote, then unmarshal:
type Review struct {
	ReviewName string `json:"review_name"`
	Verdict    string `json:"verdict"`
	Health     []struct {
		Area, Status, Note string
	} `json:"health"`
	Findings []struct {
		Severity, Category, Title, Detail, Lines string
		FixCode                                  string `json:"fix_code"`
	} `json:"findings"`
	QuickWins []struct {
		Change, Impact string
	} `json:"quick_wins"`
	Rewrite struct {
		Filename, Code string
	} `json:"rewrite"`
}
var wrapper struct{ Output string `json:"output"` }
json.Unmarshal(job.Output, &wrapper)
var review Review
json.Unmarshal([]byte(wrapper.Output), &review)

fmt.Printf("%s: %s\n", review.ReviewName, review.Verdict)
for _, a := range review.Health {
	fmt.Printf("  [%s] %s: %s\n", a.Status, a.Area, a.Note)
}
for _, f := range review.Findings {
	fmt.Printf("  (%s) %s: %s\n", f.Severity, f.Category, f.Title)
}
for _, w := range review.QuickWins {
	fmt.Printf("  %s   -- %s\n", w.Change, w.Impact)
}
os.WriteFile(review.Rewrite.Filename, []byte(review.Rewrite.Code), 0o644) // optimized.js
String envelope = api("POST", "/run", jsonPayload);
String jobId = /* data.job_id via your JSON library */;

while (true) {
    String job = api("GET", "/jobs/" + jobId, null);
    String status = /* data.status */;
    if (status.equals("succeeded") || status.equals("failed")) break;
    Thread.sleep(1500);
}
// The review is at data.output.output as a JSON string — parse it again, then read
// review_name, verdict, overview, health[] (five areas with area/status/note),
// findings[] (severity/category/title/detail/lines/fix_code), quick_wins[] (change/impact),
// coverage_check[] (id/addressed/note), rewrite{filename, code}, next_steps[] and summary.
// Finally write the optimized rewrite to disk:
//   Files.writeString(Path.of(rewriteFilename), rewriteCode);   // optimized.js
started = api("POST", "/run", payload)

job = nil
loop do
  job = api("GET", "/jobs/#{started["job_id"]}")
  break if %w[succeeded failed].include?(job["status"])
  sleep 1.5
end
raise (job["error"] || "run failed") if job["status"] == "failed"

raw = job["output"].is_a?(Hash) ? job["output"].fetch("output", job["output"]) : job["output"]
review = raw.is_a?(String) ? JSON.parse(raw) : raw

puts "#{review["review_name"]}: #{review["verdict"]}"
review["health"].each { |a| puts "  [#{a["status"]}] #{a["area"]}: #{a["note"]}" }
review["findings"].each do |f|
  puts "  (#{f["severity"]}) #{f["category"]}: #{f["title"]}"
  puts "      #{f["fix_code"]}" unless f["fix_code"].to_s.empty?
end
review["quick_wins"].each { |w| puts "  #{w["change"]}   -- #{w["impact"]}" }
review["coverage_check"].each { |c| puts "  #{c["id"]}: #{c["addressed"] ? "ok" : "SET ASIDE"}" }

File.write(review["rewrite"]["filename"], review["rewrite"]["code"])   # optimized.js
$started = api("POST", "/run", $payload);

do {
    sleep(2);
    $job = api("GET", "/jobs/" . $started["job_id"]);
} while (!in_array($job["status"], ["succeeded", "failed"]));

if ($job["status"] === "failed") {
    throw new Exception($job["error"] ?? "run failed");
}

$raw = is_array($job["output"]) ? ($job["output"]["output"] ?? $job["output"]) : $job["output"];
$review = is_string($raw) ? json_decode($raw, true) : $raw;

echo "{$review['review_name']}: {$review['verdict']}\n";
foreach ($review["health"] as $a) {
    echo "  [{$a['status']}] {$a['area']}: {$a['note']}\n";
}
foreach ($review["findings"] as $f) {
    echo "  ({$f['severity']}) {$f['category']}: {$f['title']}\n";
    if ($f["fix_code"] !== "") { echo "      {$f['fix_code']}\n"; }
}
foreach ($review["quick_wins"] as $w) {
    echo "  {$w['change']}   -- {$w['impact']}\n";
}
foreach ($review["coverage_check"] as $c) {
    echo "  {$c['id']}: " . ($c["addressed"] ? "ok" : "SET ASIDE") . "\n";
}

file_put_contents($review["rewrite"]["filename"], $review["rewrite"]["code"]);   // optimized.js
var started = await SkillSafe.ApiAsync(HttpMethod.Post, "/run", payload);
var jobId = started.GetProperty("job_id").GetString();

JsonElement job;
while (true)
{
    job = await SkillSafe.ApiAsync(HttpMethod.Get, $"/jobs/{jobId}");
    var status = job.GetProperty("status").GetString();
    if (status is "succeeded" or "failed") break;
    await Task.Delay(1500);
}

var rawText = job.GetProperty("output").GetProperty("output").GetString();
using var doc = JsonDocument.Parse(rawText!);
var review = doc.RootElement;

Console.WriteLine($"{review.GetProperty("review_name")}: {review.GetProperty("verdict")}");
foreach (var a in review.GetProperty("health").EnumerateArray())
{
    Console.WriteLine($"  [{a.GetProperty("status")}] {a.GetProperty("area")}: {a.GetProperty("note")}");
}
foreach (var f in review.GetProperty("findings").EnumerateArray())
{
    Console.WriteLine($"  ({f.GetProperty("severity")}) {f.GetProperty("category")}: " +
                      $"{f.GetProperty("title")}");
}
foreach (var w in review.GetProperty("quick_wins").EnumerateArray())
{
    Console.WriteLine($"  {w.GetProperty("change")}   -- {w.GetProperty("impact")}");
}

var rewrite = review.GetProperty("rewrite");
await File.WriteAllTextAsync(rewrite.GetProperty("filename").GetString()!,   // optimized.js
                             rewrite.GetProperty("code").GetString()!);

The model is asked for one JSON object and nothing else, but a stray code fence or preamble is always possible. Strip a leading ```json fence, take the text between the first { and the last }, and only then parse — that is what the app does before it falls back to a retry_note reformat run.

The review object — output schema

One JSON object, always the same shape. Every array is present (findings and quick_wins are empty only if genuinely nothing applies); health always has exactly the five areas, and rewrite.code is never empty. If the paste was too thin to review responsibly, you still get this object: what is there gets reviewed, the verdict says the paste is thin, and what you would need to show lands in next_steps. If the paste is not code at all, you still get the object — one critical finding explaining what arrived, every health area at risk, and a rewrite.code comment block saying what to paste instead.

FieldTypeMeaning
review_namestringA short name for the review, taken from the code's own function or domain naming.
verdictstringOne or two sentences: the overall state and the single most important fix.
overviewstringOne or two paragraphs: what this code does, the language and stack inferred, the pattern behind what was found, and whether it explains the reported slow path.
healtharray of 5{area, status, note} — the five areas listed below, each exactly once. status is good (nothing material), risk (works, with caveats) or bad (a critical or high finding lives here). Each note references something concrete in the pasted code; an area the paste gives no evidence for is good with a note saying it does not apply, never an invented risk.
findingsarray{severity, category, title, detail, lines, fix_code}. severity is critical | high | medium | low; category is data-access, memory, cpu-algorithms, network-io or rendering. detail quotes the function, variable, query or JSX it concerns; lines is a reference like "lines 12-18" or an empty string; fix_code is a corrected snippet using your own names, or an empty string when the finding is a trade-off rather than a mechanical fix.
quick_winsarray{change, impact} — at most five, ordered by impact-per-effort. Each change is a one-line fix you could ship today, drawn from the findings, with the measurable impact it buys.
coverage_checkarray{id, addressed, note} — one entry per prescan_facts item you sent (ap:await-in-loop, hotspot:loadOrders, …), saying where the review covers it or why it was set aside (a pattern hit can be a false positive; the note says so). Nothing you flagged is silently dropped.
rewriteobject{filename, code}filename matches the language (optimized.js, optimized.py, …), and code is your own worst hotspot optimized: same function, same behaviour, the findings that touch it fixed, your naming and comments preserved. It is a complete drop-in replacement for that function or component, not a fragment.
next_stepsstring[]Ordered and concrete: profile the named path with a named tool, add the index behind the hot query, measure before and after, and so on.
summarystring3–5 sentences an engineer could paste into a PR review.

The five health areas, in order, spelled exactly like this:

areaWhat its note covers
Data accessN+1 queries in loops, missing LIMIT or pagination on unbounded reads, SELECT * over the columns actually needed, missing connection pooling.
Memory & resourcesListeners never removed, intervals never cleared, caches and arrays that grow without bounds, missing unmount and destroy cleanup.
CPU & algorithmsO(n^2)-or-worse passes over data that can be large, unmemoized repeated computation, string concatenation in loops, redundant sort and filter passes.
Network & I/OMissing caching for hot read-mostly data, sequential awaits that could run in parallel with Promise.all, over-fetching, missing request deduplication.
Rendering & UIUnnecessary re-renders where the tree is hot, missing memo/useMemo/useCallback, missing list virtualization, synchronous heavy work on the main thread, oversized bundles.

A small, realistic result for the loadOrders paste above, trimmed for length:

{
  "review_name": "loadOrders order fan-out",
  "verdict": "loadOrders issues one query per user id and awaits each in turn, so latency
              grows linearly with the input; batch the fan-out before anything else.",
  "overview": "A Node data-access helper that takes a list of user ids and collects their
               orders. The language is JavaScript on a backend surface. The problems are the
               classic set: a query inside a loop, sequential awaits, an unbounded SELECT *,
               and this fully explains the 8-second dashboard you reported.",
  "health": [
    { "area": "Data access", "status": "bad",
      "note": "db.query runs once per id inside the for loop over userIds — a textbook N+1." },
    { "area": "Memory & resources", "status": "good",
      "note": "orders grows with the result set but nothing is retained past the return." },
    { "area": "CPU & algorithms", "status": "risk",
      "note": "orders.push(...rows) spreads whole result arrays; large batches blow the
               argument limit and copy more than a concat would." },
    { "area": "Network & I/O", "status": "bad",
      "note": "Every await blocks the next query; the round trips are serialized." },
    { "area": "Rendering & UI", "status": "good",
      "note": "Backend data-access code with no rendering surface — the area does not apply." }
  ],
  "findings": [
    { "severity": "critical", "category": "data-access",
      "title": "loadOrders queries inside a loop",
      "detail": "'for (const id of userIds) { const rows = await db.query(...) }' issues one
                 statement per id; 500 ids means 500 round trips.",
      "lines": "lines 3-6",
      "fix_code": "const rows = await db.query(
                     \"SELECT id, user_id, total FROM orders WHERE user_id = ANY($1) LIMIT 1000\",
                     [userIds]);" },
    { "severity": "high", "category": "network-io",
      "title": "Sequential awaits serialize the round trips",
      "detail": "Each await inside the loop waits for the previous one, so total latency is
                 the sum of every query rather than the slowest.",
      "lines": "lines 4",
      "fix_code": "const results = await Promise.all(userIds.map((id) => db.query(sql, [id])));" },
    { "severity": "medium", "category": "data-access",
      "title": "SELECT * with no LIMIT",
      "detail": "'SELECT * FROM orders WHERE user_id = $1' reads every column and every row a
                 user has ever had; the dashboard renders a handful.",
      "lines": "lines 4",
      "fix_code": "SELECT id, user_id, total FROM orders WHERE user_id = $1
                     ORDER BY created_at DESC LIMIT 50" }
  ],
  "quick_wins": [
    { "change": "Replace the per-id loop with a single WHERE user_id = ANY($1) query.",
      "impact": "Cuts 500 round trips to 1; the dashboard drops from seconds to
                 tens of milliseconds." },
    { "change": "Name the three columns the dashboard needs instead of SELECT *.",
      "impact": "Smaller rows over the wire and an index-only scan becomes possible." }
  ],
  "coverage_check": [
    { "id": "ap:await-in-loop", "addressed": true,
      "note": "Confirmed — the critical finding on loadOrders is exactly this hit." },
    { "id": "hotspot:loadOrders", "addressed": true,
      "note": "It is the worst hotspot and is the function rewritten below." }
  ],
  "rewrite": { "filename": "optimized.js", "code": "async function loadOrders(userIds) {\n …" },
  "next_steps": [
    "Add an index on orders (user_id, created_at DESC) to serve the batched query.",
    "Measure the endpoint before and after with your APM p95, not a single local run.",
    "Cap the batch: chunk userIds so one dashboard cannot ask for 50k rows."
  ],
  "summary": "One critical N+1, one high serialization finding, and an unbounded read. …"
}

The rewrite is a starting point, not a merge: it is written to be a drop-in replacement and self-consistent with the findings, but it is AI-generated and it changes the query shape of a hot path. Review it, run your own tests against it, and measure before and after before it goes anywhere near production.

Step 5 — Stream the review as it is written

POST /run-stream

/run-stream takes exactly the same body as /run but answers with server-sent events, so you can show progress instead of a spinner — useful here because the corrected rewrite makes for a long reply. This app's own progress panel is this endpoint. Events are separated by a blank line; each has an event: line and a data: line carrying JSON.

EventPayloadMeaning
job{job_id, status}Sent once, when the job is accepted — show "starting".
delta{text}A chunk of the reply, in order. Append it; the accumulated length is your only progress signal (the total is not known in advance).
done{job_id, status, charged_credits, output}The final, authoritative result — read the review from output.output rather than trusting concatenated deltas, and the settled price from charged_credits.
error{code, message}Replaces done when the run fails.
# -N disables buffering so events print as they arrive
curl -N -s -X POST "$API/run-stream" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -H "Idempotency-Key: review-$(date +%s)" \
  -d @input.json

# event: job
# data: {"job_id":"job_...","status":"running"}
#
# event: delta
# data: {"text":"{\"review_name\":\"orders"}
# ...
# event: done
# data: {"job_id":"job_...","status":"succeeded","charged_credits":612,"output":{"output":"{...}"}}
import json, requests

result = None
with requests.post(
    API + "/run-stream",
    headers={"Authorization": f"Bearer {TOKEN}",
             "Idempotency-Key": "review-001"},
    json=payload,
    stream=True,
) as r:
    r.raise_for_status()
    event = None
    for line in r.iter_lines(decode_unicode=True):
        if not line:
            continue
        if line.startswith("event:"):
            event = line[len("event:"):].strip()
        elif line.startswith("data:"):
            data = json.loads(line[len("data:"):].strip())
            if event == "delta":
                print(".", end="", flush=True)          # live progress
            elif event == "done":
                result = data
            elif event == "error":
                raise RuntimeError(data.get("message", "run failed"))

review = json.loads(result["output"]["output"])         # authoritative
print("charged:", result["charged_credits"], "-", review["review_name"])
for area in review["health"]:
    print(f'  [{area["status"]}] {area["area"]}')
open(review["rewrite"]["filename"], "w", encoding="utf-8").write(review["rewrite"]["code"])
const res = await fetch(API + "/run-stream", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${TOKEN}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify(payload),
});

const reader = res.body.getReader();
const decoder = new TextDecoder();
let buf = "", done = null;

for (;;) {
  const chunk = await reader.read();
  if (chunk.done) break;
  buf += decoder.decode(chunk.value, { stream: true });
  const frames = buf.split("\n\n");
  buf = frames.pop();
  for (const frame of frames) {
    const name = /^event:\s*(.+)$/m.exec(frame)?.[1];
    const body = /^data:\s*(.+)$/m.exec(frame)?.[1];
    if (!name || !body) continue;
    const data = JSON.parse(body);
    if (name === "delta") process.stdout.write(".");   // live progress
    if (name === "done") done = data;
    if (name === "error") throw new Error(data.message ?? "run failed");
  }
}

const review = JSON.parse(done.output.output);
console.log(`\n${done.charged_credits} credits - ${review.review_name}`);
for (const area of review.health) console.log(`  [${area.status}] ${area.area}`);
writeFileSync(review.rewrite.filename, review.rewrite.code);   // improved.sql
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", API+"/run-stream", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", "review-001")

res, err := http.DefaultClient.Do(req)
if err != nil {
	log.Fatal(err)
}
defer res.Body.Close()

var event string
var final map[string]any
sc := bufio.NewScanner(res.Body)
sc.Buffer(make([]byte, 0, 64*1024), 4*1024*1024)
for sc.Scan() {
	line := sc.Text()
	switch {
	case strings.HasPrefix(line, "event:"):
		event = strings.TrimSpace(strings.TrimPrefix(line, "event:"))
	case strings.HasPrefix(line, "data:"):
		var data map[string]any
		json.Unmarshal([]byte(strings.TrimPrefix(line, "data:")), &data)
		switch event {
		case "delta":
			fmt.Print(".") // live progress
		case "done":
			final = data
		case "error":
			log.Fatal(data["message"])
		}
	}
}
// final["output"].(map[string]any)["output"].(string) is the review JSON —
// unmarshal it into the Review struct from step 4, then write review.Rewrite.Code to disk.
// Java 17+ — read the stream line by line instead of buffering the body.
var req = HttpRequest.newBuilder(URI.create(API + "/run-stream"))
    .header("Authorization", "Bearer " + TOKEN)
    .header("Content-Type", "application/json")
    .header("Idempotency-Key", "review-001")
    .POST(HttpRequest.BodyPublishers.ofString(jsonPayload))
    .build();

var res = HTTP.send(req, HttpResponse.BodyHandlers.ofLines());
String event = null, done = null;
for (String line : (Iterable<String>) res.body()::iterator) {
    if (line.startsWith("event:")) {
        event = line.substring(6).trim();
    } else if (line.startsWith("data:")) {
        String data = line.substring(5).trim();
        if ("delta".equals(event)) System.out.print(".");   // live progress
        else if ("done".equals(event)) done = data;
        else if ("error".equals(event)) throw new RuntimeException(data);
    }
}
// parse `done`, then parse data.output.output again — it is a JSON string holding
// review_name, health[], findings[], indexes[], rewrite{filename, code} and the rest.
require "net/http"
require "json"

uri = URI(API + "/run-stream")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{TOKEN}"
req["Content-Type"] = "application/json"
req["Idempotency-Key"] = "review-001"
req.body = payload.to_json

event = nil
done = nil
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
  http.request(req) do |res|
    res.read_body do |chunk|
      chunk.each_line do |line|
        line = line.strip
        if line.start_with?("event:")
          event = line.delete_prefix("event:").strip
        elsif line.start_with?("data:")
          data = JSON.parse(line.delete_prefix("data:").strip)
          case event
          when "delta" then print "."           # live progress
          when "done"  then done = data
          when "error" then raise (data["message"] || "run failed")
          end
        end
      end
    end
  end
end

review = JSON.parse(done["output"]["output"])
puts "\n#{done["charged_credits"]} credits - #{review["review_name"]}"
review["health"].each { |a| puts "  [#{a["status"]}] #{a["area"]}" }
File.write(review["rewrite"]["filename"], review["rewrite"]["code"])   # improved.sql
$event = null;
$done  = null;

$ch = curl_init(API . "/run-stream");
curl_setopt_array($ch, [
    CURLOPT_POST       => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer $TOKEN",
        "Content-Type: application/json",
        "Idempotency-Key: review-001",
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
    CURLOPT_WRITEFUNCTION => function ($ch, $chunk) use (&$event, &$done) {
        foreach (explode("\n", $chunk) as $line) {
            $line = trim($line);
            if (str_starts_with($line, "event:")) {
                $event = trim(substr($line, 6));
            } elseif (str_starts_with($line, "data:")) {
                $data = json_decode(trim(substr($line, 5)), true);
                if ($event === "delta") { echo "."; }        // live progress
                elseif ($event === "done") { $done = $data; }
                elseif ($event === "error") { throw new Exception($data["message"] ?? "run failed"); }
            }
        }
        return strlen($chunk);
    },
]);
curl_exec($ch);
curl_close($ch);

$review = json_decode($done["output"]["output"], true);
echo "\n{$done['charged_credits']} credits - {$review['review_name']}\n";
foreach ($review["health"] as $a) { echo "  [{$a['status']}] {$a['area']}\n"; }
file_put_contents($review["rewrite"]["filename"], $review["rewrite"]["code"]);   // improved.sql
var req = new HttpRequestMessage(HttpMethod.Post, Api + "/run-stream") {
    Content = JsonContent.Create(payload),
};
req.Headers.Add("Idempotency-Key", "review-001");

using var res = await Http.SendAsync(req, HttpCompletionOption.ResponseHeadersRead);
using var reader = new StreamReader(await res.Content.ReadAsStreamAsync());

string? evt = null, done = null;
while (await reader.ReadLineAsync() is { } line)
{
    if (line.StartsWith("event:")) evt = line[6..].Trim();
    else if (line.StartsWith("data:"))
    {
        var data = line[5..].Trim();
        if (evt == "delta") Console.Write(".");            // live progress
        else if (evt == "done") done = data;
        else if (evt == "error") throw new Exception(data);
    }
}

using var final = JsonDocument.Parse(done!);
var text = final.RootElement.GetProperty("output").GetProperty("output").GetString();
using var reviewDoc = JsonDocument.Parse(text!);
var review = reviewDoc.RootElement;
Console.WriteLine(review.GetProperty("review_name"));
foreach (var a in review.GetProperty("health").EnumerateArray())
    Console.WriteLine($"  [{a.GetProperty("status")}] {a.GetProperty("area")}");
var rewrite = review.GetProperty("rewrite");
await File.WriteAllTextAsync(rewrite.GetProperty("filename").GetString()!,   // improved.sql
                             rewrite.GetProperty("code").GetString()!);

In a browser, the native EventSource only speaks GET, and this endpoint is a POST — read the fetch response body incrementally, as the JavaScript sample above does. On an idempotent replay the server may answer with a plain JSON envelope instead of an event stream; check the Content-Type before you start parsing frames.