Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Pao Laravel Package

laravel/pao

Agent-optimized output for PHP tools. Auto-detects AI agents (Claude Code, Cursor, Devin, Gemini CLI) and replaces verbose PHPUnit/Pest/Paratest/PHPStan output with minimal structured JSON; cleans Laravel Artisan output too. Zero config; human output unchanged.

View on GitHub
Deep Wiki
Context7

Introduction

Laravel PAO is agent-optimized output for PHP tools. It works with any PHP project — Laravel, Symfony, Laminas, vanilla PHP, or anything else that uses PHPUnit, Pest, Paratest, PHPStan, Rector, or Laravel Artisan.

It detects when your tools are running inside an AI agent — Claude Code, Cursor, Devin, Gemini CLI, and others — and replaces the verbose, human-readable output with compact, super minimal, structured JSON. For Laravel Artisan commands, it strips ANSI colors, box-drawing characters, and excess whitespace. Zero config — just install and it works.

Installation

Requires PHP 8.3+ — Works with PHPUnit 12-13, Pest 4-5, Paratest, PHPStan, Rector, and Laravel 12+.

composer require laravel/pao --dev

That's it. PAO hooks into PHPUnit, Pest, Paratest, PHPStan, and Rector automatically through Composer's autoloader. For Laravel projects, a service provider is auto-discovered to clean Artisan command output.

PAO only activates when it detects an AI agent (Claude Code, Cursor, Devin, Gemini CLI, etc.). When you or your team run tools directly in the terminal, the output is completely unchanged — same colors, same formatting, same experience. Zero impact on human workflows.

Before & After

Your test suite with 1,000 tests goes from this:

PHPUnit 12.5.14 by Sebastian Bergmann and contributors.

.............................................................   61 / 1002 (  6%)
.............................................................  122 / 1002 ( 12%)
...
..........................                                    1002 / 1002 (100%)

Time: 00:00.321, Memory: 46.50 MB

OK (1002 tests, 1002 assertions)

To this:

{
  "tool": "phpunit",
  "result": "passed",
  "tests": 1002,
  "passed": 1002,
  "duration_ms": 321
}

That's up to 99.8% fewer AI tokens. The output is constant-size regardless of how many tests you have — and when tests fail, it includes file paths, line numbers, and failure messages.

Extra output from Pest plugins like --coverage or --profile is captured, cleaned of ANSI codes and decorations, and included as a raw array in the JSON:

{
  "tool": "pest",
  "result": "passed",
  "tests": 1002,
  "passed": 1002,
  "duration_ms": 1520,
  "raw": [
    "Http/Controllers/Controller 100.0%",
    "Models/User 0.0%",
    "Total: 33.3 %"
  ]
}

Laravel Artisan

When installed in a Laravel 12+ application, PAO automatically cleans Artisan command output in agent environments — stripping ANSI colors, box-drawing characters, dot separators, and excess whitespace:

# Before (without PAO) — 2,111 characters
  Environment ................................................................
  Application Name ................................................... Laravel
  Laravel Version ..................................................... 13.3.0
  PHP Version .......................................................... 8.5.4
  Debug Mode ......................................................... ENABLED

# After (with PAO) — 535 characters
 Environment ..
 Application Name .. Laravel
 Laravel Version .. 13.3.0
 PHP Version .. 8.5.4
 Debug Mode .. ENABLED

Up to 75% fewer tokens on commands like about, db:show, and migrate:status — same information, no decoration.

PHPStan

PHPStan output is also converted to structured JSON:

{
  "tool": "phpstan",
  "result": "failed",
  "errors": 2,
  "error_details": {
    "/app/Http/Controllers/Controller.php": [
      {
        "line": 9,
        "message": "Method Controller::index() should return int but returns string.",
        "identifier": "return.type"
      },
      {
        "line": 14,
        "message": "Call to an undefined method Controller::doesNotExist().",
        "identifier": "method.notFound"
      }
    ]
  }
}

Rector

Rector is automatically run with its native JSON output format:

{
  "tool": "rector",
  "result": "failed",
  "totals": {
    "changed_files": 1,
    "errors": 0
  },
  "file_diffs": [
    {
      "file": "app/Models/User.php",
      "diff": "--- Original\n+++ New\n@@ ...",
      "applied_rectors": [
        "Rector\\Php54\\Rector\\Array_\\LongArrayToShortArrayRector"
      ]
    }
  ],
  "changed_files": [
    "app/Models/User.php"
  ]
}

Contributing

Thank you for considering contributing to Laravel! The contribution guide can be found in the Laravel documentation.

Code of Conduct

In order to ensure that the Laravel community is welcoming to all, please review and abide by the Code of Conduct.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

License

The Laravel PAO is open-sourced software licensed under the MIT license.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware