Skip to content

Switch agent output from JSON to TOON for ~19% token reduction#4940

Closed
pushpak1300 wants to merge 2 commits intophpstan:2.2.xfrom
pushpak1300:feat/toon-agent-output
Closed

Switch agent output from JSON to TOON for ~19% token reduction#4940
pushpak1300 wants to merge 2 commits intophpstan:2.2.xfrom
pushpak1300:feat/toon-agent-output

Conversation

@pushpak1300
Copy link

@pushpak1300 pushpak1300 commented Feb 15, 2026

This pull request switches the AI agent output format from JSON to TOON (Token-Oriented Object Notation) — a compact, machine-parseable format optimized for LLM contexts.

Follows up on #4938.

Why:

TOON saves ~15% tokens compared to JSON while keeping the same data structure fully machine-parseable. It achieves this by declaring field names once as a header (messages[9]{message,line,ignorable,identifier}:) and encoding each error as a single comma-separated line — no repeated keys, braces, or brackets per entry.

Token comparison (9 real errors, measured with o200k_base tokenizer):

Format Characters Tokens vs JSON
table 2,667 379 -4%
json 1,705 394 baseline
toon 1,377 334 -15%

How detection works:

  1. When Claude Code runs PHPStan, it sets the CLAUDECODE / CLAUDE_CODE environment variable
  2. When Cursor runs PHPStan, it sets CURSOR_TRACE_ID / CURSOR_AGENT
  3. Other agents set their own env vars (GEMINI_CLI, CODEX_SANDBOX, AI_AGENT, AUGMENT_AGENT, OPENCODE, REPL_ID, etc.)
  4. PHPStan detects these via shipfastlabs/agent-detector and automatically switches to TOON format + suppresses progress bar animations — no flags needed

What changed:

  1. Added helgesverre/toon dependency for TOON encoding
  2. Created ToonErrorFormatter — builds the same error data structure as JsonErrorFormatter but encodes as TOON
  3. Agent detection now switches to toon format instead of json
  4. TOON format is also available directly via --error-format=toon

Output:

totals:
  errors: 0
  file_errors: 1
files:
  "/path/to/file.php":
    errors: 1
    messages[1]{message,line,ignorable,identifier}:
      "Error message",10,true,error.id
errors[0]:

Explicit --error-format=table or config errorFormat: table always takes priority over agent detection.

related laravel/pint#415

Adds helgesverre/toon and creates ToonErrorFormatter that outputs in
TOON (Token-Oriented Object Notation) format. When an AI agent is
detected, PHPStan now outputs in TOON instead of JSON, reducing token
consumption while remaining machine-parseable.

Follows up on phpstan#4938.
@phpstan-bot
Copy link
Collaborator

You've opened the pull request against the latest branch 2.2.x. PHPStan 2.2 is not going to be released for months. If your code is relevant on 2.1.x and you want it to be released sooner, please rebase your pull request and change its target to 2.1.x.

@pushpak1300 pushpak1300 marked this pull request as draft February 15, 2026 13:30
Comment on lines +27 to +28
"helgesverre/toon": "^1.0",
"shipfastlabs/agent-detector": "^1.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder what's your policy about added library in PHPStan @ondrejmirtes ?
Adding library with low number of star and/or low number of contributors/maintainers is always a risk (especially for security reason).
I always have this story in mind

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not worth it here...

@ondrejmirtes
Copy link
Member

I said you should try raw format instead 😊

@VincentLanglet
Copy link
Contributor

It could still be exposed as a standalone extension pushpak1300/phpstan-toon-formatter maybe ?

I'm not sure about it but I think PHPStan expose enough extension point to add custom formatter, no ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants