Your AI coding bill is, increasingly, a data-formatting problem. Every time an agent pulls your open issues, your quality gate status, or your dependency risks into its context window, it pays tokens for the shape of that data as well as the content. Most of that data goes to the agent as JSON, and JSON is verbose. There is a one-flag fix for the most common case, and it costs you nothing but a keystroke.
sonar list issues can emit its results as TOON instead of JSON:
sonar list issues -p my-org_my-app --format toonThis post measures what that swap saves, shows you how to reproduce the measurement on your own data, and puts it in the larger context of where Sonar is already trimming tokens: Sonar Vortex's Context Augmentation on the way in, and cleaner code itself across the whole session.
What is TOON format and how does it work?
TOON (Token-Oriented Object Notation) is a compact, lossless encoding of the JSON data model, designed specifically for LLM input. It combines YAML-style indentation for nested objects with a CSV-style tabular layout for uniform arrays of objects. A list of issues is exactly that: an array of records with the same fields. That is TOON's sweet spot.
Here is the same three-issue result in each format. First the default, --format json:
{
"issues": [
{ "key": "AZ1002fQ9x", "rule": "javasecurity:S3649", "severity": "BLOCKER", "type": "VULNERABILITY", "component": "my-org_my-app:src/main/java/com/acme/UserRepo.java", "line": 29, "message": "Change this code to not construct SQL queries directly from user-controlled data.", "status": "OPEN", "effort": "5min" },
{ "key": "AZ1007fQ9x", "rule": "java:S2076", "severity": "BLOCKER", "type": "VULNERABILITY", "component": "my-org_my-app:src/main/java/com/acme/AuthFilter.java", "line": 61, "message": "Make sure that constructing this OS command is safe here.", "status": "OPEN", "effort": "30min" },
{ "key": "AZ1013fQ9x", "rule": "java:S1481", "severity": "MINOR", "type": "CODE_SMELL", "component": "my-org_my-app:src/main/java/com/acme/OrderService.java", "line": 140, "message": "Remove this unused local variable.", "status": "OPEN", "effort": "5min" }
],
"paging": { "pageIndex": 1, "pageSize": 500, "total": 3 }
} Now --format toon:
issues[3]{key,rule,severity,type,component,line,message,status,effort}:
AZ1002fQ9x,"javasecurity:S3649",BLOCKER,VULNERABILITY,my-org_my-app:src/main/java/com/acme/UserRepo.java,29,Change this code to not construct SQL queries directly from user-controlled data.,OPEN,5min
AZ1007fQ9x,"java:S2076",BLOCKER,VULNERABILITY,my-org_my-app:src/main/java/com/acme/AuthFilter.java,61,Make sure that constructing this OS command is safe here.,OPEN,30min
AZ1013fQ9x,"java:S1481",MINOR,CODE_SMELL,my-org_my-app:src/main/java/com/acme/OrderService.java,140,Remove this unused local variable.,OPEN,5min
paging:
pageIndex: 1
pageSize: 500
total: 3Same data. The field names are declared once in the header ({key,rule,severity,...}) instead of repeating on every record, and the braces, quotes, and repetition collapse into one row per issue. Crucially, the [3] length and the field header give the model an explicit schema to validate against, so this is not a lossy shortcut like flattening to CSV.
How much does TOON reduce token usage compared to JSON?
I generated a representative 25-issue result (the fields sonar list issues returns: key, rule, severity, type, component, project, line, message, status, effort, totals, paging, and next fields like flows and impacts) and encoded it three ways. Character counts, which are tokenizer-independent and easy to reproduce:
So TOON is about half the size of the default JSON and a third smaller than even minified JSON, by character count, on this payload.
Characters are not tokens, though, and this is where TOON does better than a simple size ratio suggests. Because its structure is so regular (one header, then uniform rows), it tokenizes efficiently. The TOON project's own benchmark suite, counted with the GPT-5 o200k_base tokenizer, reports for uniform tabular datasets (the same shape as an issues list):
- −60.7% tokens versus pretty JSON and −36.9% versus compact JSON on the 100-row uniform employee records dataset.
- −41.7% versus pretty JSON on the 100-repository GitHub dataset.
- Across 244 retrieval questions on four models, TOON scored 72.2% accuracy versus JSON's 71.4% while using 42.6% fewer tokens. Claude Haiku 4.5 was one of the four models, and TOON scored marginally higher there too (65.6% vs 63.5%).
The honest headline: for an issues list, expect roughly a third to a half fewer tokens than JSON, depending on whether your baseline is minified or pretty and which tokenizer your agent uses. And you are not trading comprehension for size; the accuracy held or improved.
A note on method. The character numbers above are mine, measured on a representative payload. The token percentages are from the TOON project's published benchmarks (o200k_base). I could not run a tokenizer in my sandbox to produce a Sonar-specific token count, which is exactly why the next section shows you how to get the real number for your data.
Measure it yourself
The TOON CLI has a --stats flag that prints the token savings for any JSON you feed it. Point it at real Sonar output:
# Grab your issues as JSON (the default)
sonar list issues -p my-org_my-app --severities BLOCKER,CRITICAL --format json > issues.json
# Convert to TOON and print the token-savings report
npx @toon-format/cli issues.json --statsThen, once you have seen the number, wire the compact form straight into whatever consumes it:
sonar list issues -p my-org_my-app --format toonTwo flag facts worth knowing: sonar list issues require --project (-p), and --format accepts json (default), toon, table, and csv. Use a table when a human is reading, toon when an agent is.
When should you use JSON instead of TOON for LLM input?
TOON is not a universal win, and saying so keeps you honest with your own FinOps stakeholders. Its advantage comes from uniform, tabular data. For deeply nested or non-uniform structures, compact JSON can actually use fewer tokens. An issues list is uniform, so it lands squarely in TOON's favor; a deeply nested config blob would not. When in doubt, run it through --stats and let the number decide.
The bigger picture: three places Sonar trims the token bill
The reason this matters beyond one flag is that Sonar's research reframed the cost problem. In a controlled 540-run study, cleaner codebases used 7.2% fewer input tokens and 8.5% fewer output tokens with no drop in task completion. The mechanism is the quotable part: what drives the cost is not how much the agent writes, it is how much it has to look at. Format the world compactly and give the agent less to wade through, and the bill drops.
That single idea shows up in three places, and --format toon is the cheapest of them:
- On the way in: Sonar Vortex Context Augmentation. Instead of letting the agent blind-read entire files to build a mental model, Vortex injects only the relevant guidelines, architecture, and semantic-navigation results before the agent writes. Sonar reports this cuts token consumption by up to 36%, largely by replacing broad file reads with precise, structured context.
- Across the whole session: cleaner code. The 540-run result above. Verified, gate-passing code is simply cheaper to operate on, run after run.
- On the way out: compact tool results. When the agent reads your issues or dependency risks,
--format toonis the same "same information, fewer tokens" move applied to Sonar's own output —sonar list issuesandsonar analyze dependency-risksboth accept it. It is a one-line change with no downstream cost, because TOON is a lossless representation of the JSON your scripts already parse.
Context Augmentation trims the input side; TOON trims the tool-result side; clean code trims the whole session. They stack. If you are trying to put a number on "our agent spend is a code-quality problem," this is the flag you can ship this afternoon while the larger work lands.
How to get started reducing token usage with Sonar and TOON
Switching sonar list issues to --format toon cuts the size of the data your agent ingests by roughly a third to a half versus JSON, with equal or better comprehension, and you can prove the exact token figure on your own data with npx @toon-format/cli --stats. It is the smallest, most reversible entry into the tokenomics-of-quality story, and it points straight at the bigger levers: Context Augmentation on the input side and clean, verified code across the session.

