Skip to content

Add AI agent detection to auto-switch to raw output#4942

Open
pushpak1300 wants to merge 3 commits intophpstan:2.1.xfrom
pushpak1300:feat/agent-raw-output
Open

Add AI agent detection to auto-switch to raw output#4942
pushpak1300 wants to merge 3 commits intophpstan:2.1.xfrom
pushpak1300:feat/agent-raw-output

Conversation

@pushpak1300
Copy link

@pushpak1300 pushpak1300 commented Feb 15, 2026

This pull request adds AI agent detection that automatically switches PHPStan to raw error format and suppresses progress bar output when executed within Claude Code, Cursor, Gemini CLI, Codex, OpenCode, Augment, Replit

Why:

The default PHPStan output is designed for humans - colorful tables, progress bars with animations, and formatted summaries. AI agents need something different: minimal output that saves context window and reduces token cost, unambiguous error details with file paths and line numbers, and no progress bar animations that waste tokens on redraw noise.

Why raw format over JSON?

The raw format (file:line:message, one error per line) is significantly more token-efficient than JSON:

Scenario JSON Raw Token Savings
3 errors / 2 files ~185 tokens (678 chars) ~95 tokens (295 chars) ~49%
0 errors ~18 tokens (62 chars) 0 tokens (empty) 100%

How it 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, etc.)
  4. PHPStan detects these and automatically:
    • Switches to raw format (one error per line as file:line:message)
    • Suppresses progress bar output entirely (equivalent to --no-progress)

Detection is inlined (simple getenv() calls) to avoid any external dependency and maintain compatibility with all PHP versions PHPStan supports.

Output example:

/app/src/Controller/UserController.php:42:Parameter #1 $id expects int, string given.
/app/src/Service/PaymentService.php:18:Call to an undefined method proccess().

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

Related to #4939

@pushpak1300 pushpak1300 force-pushed the feat/agent-raw-output branch from 8536d19 to ae99977 Compare February 15, 2026 16:14
Switch from JSON to raw error format for AI agents. The raw format
outputs one error per line as file:line:message, which saves ~49%
tokens compared to JSON for typical error output (and 100% for
zero-error runs.

When an agent is detected, progress bar output is fully suppressed
(equivalent to --no-progress), eliminating redraw noise that wastes
tokens in agent context windows.

Token comparison (3 errors across 2 files):
- JSON: ~185 tokens (678 chars) with structural overhead per error
- Raw:   ~95 tokens (295 chars) with just file:line:message per line

Zero errors:
- JSON: ~18 tokens for empty structure
- Raw:    0 tokens (no output)

Explicit --error-format=table or config errorFormat: table always
takes priority over agent detection.
@pushpak1300 pushpak1300 force-pushed the feat/agent-raw-output branch from ae99977 to 8724e6b Compare February 15, 2026 16:19
- Extract duplicated detection logic from AgentDetectedErrorFormatter and ErrorsConsoleStyle into AgentDetector with static method
- Drop unnecessary ErrorFormatter implementation and @api tag
- Replace REPL_ID with more specific REPLIT_AGENT env var
- Fix test tearDown to clean all env vars
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.

1 participant