laravel/pao
Agent-optimized output for PHP tools. Detects AI agents (Claude Code, Cursor, Devin, Gemini CLI, etc.) and replaces verbose PHPUnit/Pest/Paratest/PHPStan/Rector and Laravel Artisan output with minimal structured JSON (and cleaner Artisan text). Zero config; human terminal output unchanged.
Installation:
composer require laravel/pao --dev
First Use Case:
php artisan test
Output (in AI agent):
{
"tool": "phpunit",
"result": "passed",
"tests": 100,
"passed": 100,
"duration_ms": 500
}
Where to Look First:
php artisan about
(Compare output with/without PAO in an AI agent.)AI Agent Integration:
PAO_AGENT=1 or agent-specific headers).Human-Friendly Fallback:
php artisan test in terminal).Laravel-Specific Patterns:
php artisan migrate:status becomes 75% smaller in token count.config/app.php.Tool-Specific Patterns:
raw array.{
"tool": "pest",
"raw": ["Coverage: 85%", "Tests: 100/100"]
}
return.type identifiers).Edge Case Handling:
.env values (e.g., APP_DEBUG=true → bool(true)).For CI/CD Pipelines:
PAO_AGENT=1 in your CI environment to force JSON output for AI processing.env:
PAO_AGENT: 1
For Local Development:
unset PAO_AGENT
Customizing Output:
TestResult class (used internally) to add custom fields to JSON.PaoServiceProvider in Laravel to modify Artisan output rules.Debugging AI Parsing:
// In a test listener or command
file_put_contents('pao_debug.json', json_encode($paoOutput, JSON_PRETTY_PRINT));
Performance:
Agent Detection False Positives:
PAO_AGENT=1 or unset it if needed:
export PAO_AGENT=0 # Disable PAO
Incomplete Output on Runtime Exits:
php artisan test fails mid-execution).v1.1.1+ to ensure results are captured before exit.Boolean Env Var Parsing:
.env values like APP_DEBUG=true might not parse as booleans.v1.1.1 for correct boolean handling.Pest Parallel Mode Quirks:
--parallel may leak raw dots (.) in output.v1.0.6+ or manually filter output:
$output = str_replace('.', '', $output);
Artisan Command-Specific Issues:
make:model) may not be optimized by PAO.PHPStan Error Limits:
raw field to access full output if needed.Verify PAO Activation:
php artisan pao:debug
Inspect JSON Output:
php artisan test > pao_output.json
jq . pao_output.json
Disable PAO for Testing:
config/app.php:
'providers' => [
// Comment out or remove:
// \Laravel\Pao\PaoServiceProvider::class,
],
Handle AI Agent-Specific Errors:
json_last_error() to validate output:
$json = json_encode($paoOutput);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \RuntimeException("Invalid JSON: " . json_last_error_msg());
}
Custom Tool Support:
Laravel\Pao\Contracts\Tool and register it in PaoServiceProvider.// app/Providers/PaoServiceProvider.php
public function registerTools()
{
$this->app->singleton(\Laravel\Pao\Contracts\Tool::class, function () {
return new class implements \Laravel\Pao\Contracts\Tool {
public function handle($output) { /* Custom logic */ }
};
});
}
Modify JSON Schema:
TestResult class to add custom fields:
namespace App\Pao;
use Laravel\Pao\TestResult as BaseTestResult;
class TestResult extends BaseTestResult
{
public function __construct()
{
parent::__construct();
$this->customField = 'value';
}
}
Artisan Output Rules:
// config/pao.php (if added)
'artisan' => [
'commands' => [
'migrate:*', // Clean all migrate commands
'!make:*', // Exclude make commands
],
],
Agent Detection Logic:
How can I help you explore Laravel packages today?