Documentation menu

Quickstart

L80 is a small CLI that publishes a benchmark or a set of findings as a plain, shareable page. You (or your agent) write JSON. The server validates it and renders it from a template it controls. Three steps to the first page: install, save a token, publish.

Install

$ curl -fsSL https://launch80.com/install.sh | sh

macOS and Linux, Intel or ARM. The script verifies a checksum and writes one binary to ~/.local/bin. If that directory is not on your PATH, the script prints the line to add. The whole script is on one page if you want to read it first.

Other install locations, and updating

Pass --prefix to the script to install somewhere other than ~/.local/bin. The script also links a lowercase l80 beside the binary when nothing else is there.

# later, to move to the newest release in place; --check only reports
$ L80 update

Get a publish token

Tokens are issued by hand right now. Ask in Discord and you will usually have one the same day. Nothing publishes without it. When it arrives, save it to disk:

# paste your token in place of <TOKEN>, then run
$ mkdir -p ~/.config/L80 && umask 077 && printf '{"token":"%s"}' '<TOKEN>' > ~/.config/L80/credentials.json
# confirm the CLI can find it and reach the server
$ L80 doctor
Use an environment variable instead of the file

L80_TOKEN takes precedence over the credentials file. Useful in CI or a container. It is still a secret: set it in the environment, not in a script you commit.

Publish

One command, depending on what you have. Each prints a URL on its last line.

# run BetterBench against a server and publish the run
$ L80 betterbench --endpoint http://localhost:8080/v1 --model qwen3-32b
# publish a BetterBench results.json you already have
$ L80 betterbench --results results.json
# publish a report you wrote by hand; see Templates for the shapes
$ L80 publish report.json --template generic.report.v1

A full BetterBench run takes a while: 20 passes per category plus prefill and concurrency sweeps. --quick is a 5-pass smoke run, and the page says so. The results file stays in the working directory. The endpoint URL and hostname are stripped before upload and the server refuses a file that still carries them.

Preview before publishing

--dry-run validates locally and reports without publishing. For L80 betterbench, add --payload-out p.json to write the exact payload that would be sent.

$ L80 betterbench --results results.json --dry-run --payload-out payload.json$ L80 publish report.json --dry-run
Naming the template

--template on the command line and "$template" in the JSON both work. Use both and they must agree, or the command stops with E_TEMPLATE_CONFLICT rather than guessing. L80 betterbench defaults to bench.betterbench.v1; pass --template bench.report.v1 for the summary layout from the same file.

BetterBench

L80 betterbench either runs BetterBench against an endpoint or reads a results.json you already have, then publishes the result. Every flag it accepts is below. Anything after -- is passed to betterbench run untouched.

--title and --summary set the heading and the paragraph under it. --section "Heading=Body" adds a prose section and repeats. --note key=value records a fact about the run and shows it as a chip, for example --note engine="vLLM 0.9.3". It also repeats.

flagdoes
--endpoint <url>OpenAI-compatible base URL to benchmark, e.g. http://host:8080/v1.
--model <name>Model name to request.
--results <file>Publish this existing results.json instead of running.
--quickShort smoke run (BetterBench --quick). The page says so.
--passes NMeasured passes per category. Default is BetterBench's 20.
--warmup NWarmup passes per category. Default is BetterBench's.
--decode, --prefill, --concurrencyRun only the named phases. Combinable.
--no-prefill, --no-concurrencySkip a sweep.
--out <path>Where results.json is written. Default ./betterbench-<model>-<time>.json.
--template <id>bench.betterbench.v1 (default) or bench.report.v1.
--title, --summaryPage heading and the paragraph under it.
--section "H=Body"Extra prose section. Repeatable.
--note k=vFact about the run, shown as a chip. Repeatable.
--engine, --hardwareLabels. bench.report.v1 only.
--dry-runRun or read, prepare the payload, do not publish.
--payload-out <path>Also write the exact payload to this path.
--jsonMachine-readable output.
--api-base <url>Server override, same as L80_API_BASE.
-- <args>Everything after -- goes to betterbench run verbatim.

From a coding agent

Everything above except the token is a shell command, so an agent can do it. Pick the variant that matches what you have, paste it into Claude Code, Cursor, or whatever runs your terminal, and come back for the link. The prompt tells the agent to stop and ask you if the token is missing.

Set up the L80 CLI so you can publish results to launch80, then publish a report.

1. Install it: curl -fsSL https://launch80.com/install.sh | sh
   If ~/.local/bin is not on PATH, add it, then confirm `L80 version` works.
2. If you are Claude Code, install the skill: L80 skills link --target claude-code
   Any other agent: run `L80 skills print` and follow that file instead.
3. Run `L80 auth status`. If it reports no token, STOP and tell me: I will save
   one to ~/.config/L80/credentials.json myself. Never ask me to paste a token
   into this chat, and never write one to a file for me.
4. Run `L80 doctor` and fix anything it flags.
5. Benchmark my server and publish the run:
   L80 betterbench --endpoint <URL> --model <MODEL>
   Ask me for the endpoint URL and model name if I have not given them.
   Use --quick only if I ask for a smoke test.
6. Give me the URL from the `published:` line and repeat every caveat the
   tool printed, especially anything about under-sampled percentiles.
Install the skill into Claude Code (optional)

The skill is a short markdown file telling an agent which template to pick, what the JSON looks like, and how to read an error. The CLI works without it; it only makes the agent better at the first try. Claude Code is the only linked target today.

# copies the skill to ~/.claude/skills; Claude Code sees it on the next session start
$ L80 skills link --target claude-code

For any other agent, print it and paste it where that tool reads instructions from:

$ L80 skills print

--force replaces an existing installation. --dev --from ./skills symlinks a checkout of the skills repo so edits are live. The full text of the skill is on the verify page.

Templates

Three layouts. The choice matters because the wrong one loses information rather than just looking plainer. Each id links to a real published example.

templateuse it forsay to your agent
bench.betterbench.v1A BetterBench run or its results.json. Produced only by L80 betterbench. Every chart and table is derived on the server from the raw samples, so the page matches the HTML report BetterBench writes beside the file.run betterbench against my server and publish it to launch80
bench.report.v1Per-category percentile data from any other harness. Tables with p50 and p99 side by side and under-sampled percentiles marked.publish this benchmark run to launch80
generic.report.v1Everything else: findings, status, test results. Title, summary, a row of metrics, prose sections.publish these findings to launch80
Payload rules that apply to every template
  • Plain text only. No links, images, or markup anywhere in a payload.
  • Unknown fields are rejected, not dropped, so a page never diverges from what you sent.
  • Metric values are strings. You format the number; the renderer never touches it.
  • L80 templates list shows the ids the server accepts, and the example pages each show a complete valid payload.

What a published page is

  • Public. Anyone with the link can read it.
  • Immutable. To change something, publish again and share the new link.
  • Unindexed. Search engines are told to stay out. Sharing the link is unaffected.
  • Self-contained. No scripts, fonts, or trackers load.
  • Labelled. Every page carries a visible “self-reported, not verified by launch80” badge.
  • Kept 5 days on the free tier, then removed. Republish to keep a result around.

L80 history lists the URLs your key has published, from any machine. With no token or no network it falls back to the local record on this machine.

Commands

commanddoes
L80 betterbench --endpoint <url> --model <m>Run BetterBench against an OpenAI-compatible server and publish the run.
L80 betterbench --results <results.json>Publish an existing BetterBench results file.
L80 publish <file.json> [--template <id>]Publish a hand-written payload. Prints the URL.
L80 templates listThe template ids the server accepts right now.
L80 historyThe share URLs this key has published, newest first.
L80 auth statusWhere the CLI is looking for a token, masked.
L80 doctorCheck connectivity, config, and credential in one shot.
L80 skills link --target claude-codeInstall the agent skill into Claude Code. Optional.
L80 skills printPrint the agent skill to stdout, for any other agent.
L80 updateInstall the latest release in place.
L80 versionPrint the version.

Every network-facing command accepts --json for machine-readable output and --api-base to override the server. Flags may come before or after the file argument. The betterbench flags have their own section.

Flags for publish, history, skills link, and update
flagdoes
publish --template <id>Template id. Or put "$template" in the JSON.
publish --dry-runValidate locally and report, without publishing.
history --limit NHow many to list, newest first. Default 50, max 200.
history --allKeep paging until the whole history is listed.
history --localRead only the local record of publishes from this machine.
skills link --forceReplace an existing installation.
skills link --dev [--from <dir>]Symlink a source checkout so edits are live.
skills link --name <skill>Which bundled skill. Default l80-test-report.
skills print [name]Which bundled skill to print. Default l80-test-report.
update --checkReport whether an update is available without installing.

Environment and files

Resolution order for the server is flag, then variable, then default. For the token it is variable, then file.

variabledoes
L80_TOKENPublish token. Overrides the credentials file.
L80_API_BASEServer to publish to. Default https://launch80.com. The --api-base flag overrides it.
L80_BETTERBENCHPath to a betterbench binary. Otherwise the one on PATH is used, or uvx bootstraps it from GitHub.
XDG_CONFIG_HOMEMoves the config directory. Default ~/.config.
CLAUDE_CONFIG_DIRWhere skills link installs. Default ~/.claude.
filewhat it is
~/.config/L80/credentials.json{"token": "..."}. Create it at mode 0600.
~/.config/L80/history.jsonlLocal record of every publish made from this machine. Read by L80 history --local.
~/.claude/skills/l80-test-report/The agent skill, after skills link.
./betterbench-<model>-<time>.jsonThe results file a run writes. --out chooses another path.

Limits

whatlimit
Payload, report templates64 KB
Payload, bench.betterbench.v14 MB
Metrics12
Categories12
Sections10
Section body4,000 characters
Publishes per key, free tier10 per rolling day
Page retention, free tier5 days

Every token is on the free tier today. A paid tier with a higher daily limit and longer retention is coming; the numbers will be posted here and in Discord when it opens. If you need more before then, ask in Discord.

Errors

Every error prints a code, a sentence, and a remedy naming the next action, and the process exits with a code an agent can branch on.

codeexitmeaning
E_TOKEN_MISSING5No credential found. L80 auth status shows where the CLI is looking.
E_UNAUTHORIZED5The token is wrong or was rotated. Ask in Discord for a new one.
E_SCHEMA_INVALID4Each listed path is the exact field to fix.
E_JSON_INVALID4The file is not valid JSON.
E_PAYLOAD_TOO_LARGE9Over the template limit. Shorten and publish again.
E_TEMPLATE_UNKNOWN10No template with that id. L80 templates list shows the current ones.
E_TEMPLATE_CONFLICT2--template and the payload's $template disagree. Pick one.
E_QUOTA_EXCEEDED6Daily limit for this key. Retry-After says when the window reopens. Do not retry in a loop.
E_RATE_LIMITED6Too many requests in a short burst from one address. Wait a moment.
E_NETWORK7Could not reach the server. L80 doctor tests the connection.
E_INPUT_INVALID3A local input problem: missing file, unreadable results.json, bad flag value.
E_USAGE2Wrong command or flags. L80 help lists them.
Exit codes
exitmeaning
0success
1internal error
2usage
3local input invalid
4payload failed validation
5authentication
6rate limited or over quota
7network
8server error
9payload too large
10unknown template

Help

Tokens, questions, and new template proposals all go through Discord. The lab notes cover the reasoning behind the templates.