jegjessing/laravel-nplusone-autofix

Reads N+1 query warnings recorded by a runtime detector, asks Claude for a minimal Eloquent fix, applies the patch, and clears the row. Ships an artisan command for Laravel 11/12/13.

Maintainers

Package info

github.com/jegjessing/laravel-nplusone-autofix

pkg:composer/jegjessing/laravel-nplusone-autofix

Transparency log

Statistics

Installs: 14

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-08-19 07:01 UTC

This package is auto-updated.

Last update: 2026-08-19 07:03:35 UTC


README

An artisan command that turns recorded N+1 query warnings into applied code fixes.

It reads rows from an nplusone_warnings table (populated by a runtime N+1 detector such as saasscaleup/laravel-n-plus-one-detector), sends each warning plus a window of the offending source to Claude, applies the returned patch in-place, and deletes the warning row.

⚠️ This command edits your source files. Always run it in a clean working tree and review git diff + your test suite before committing. Start with --dry-run.

Requirements

  • PHP 8.2+
  • Laravel 11, 12, or 13
  • A warnings table with at least id, sql, and location (path:line) columns
  • An Anthropic API key

Installation

From Packagist (once published)

composer require jegjessing/laravel-nplusone-autofix --dev

From GitHub before it's on Packagist

Add the repo to your app's composer.json, then require it:

{
    "repositories": [
        { "type": "vcs", "url": "https://github.com/jegjessing/laravel-nplusone-autofix.git" }
    ]
}
composer require jegjessing/laravel-nplusone-autofix:dev-main --dev

Local path repository (development)

When the package lives beside your app on disk, wire it in with a path repository so edits are picked up live:

{
    "repositories": [
        { "type": "path", "url": "../laravel-nplusone-autofix", "options": { "symlink": true } }
    ]
}
composer require jegjessing/laravel-nplusone-autofix:@dev --dev

The service provider is auto-discovered — no manual registration needed.

Configuration

The defaults read the standard ANTHROPIC_* env vars, so if your app already talks to Claude there is nothing to set up. To customise (table name, model, source roots), publish the config:

php artisan vendor:publish --tag=nplusone-autofix-config
Env var Default Purpose
ANTHROPIC_API_KEY Required. Anthropic API key.
ANTHROPIC_MODEL claude-sonnet-4-6 Model used to generate patches.
ANTHROPIC_BASE_URL https://api.anthropic.com API base URL.
NPLUSONE_AUTOFIX_MAX_TOKENS 4096 Max response tokens for the patch call.
NPLUSONE_AUTOFIX_TABLE nplusone_warnings Table the warnings are read from.

Usage

# Preview every proposed patch, change nothing:
php artisan nplusone:autofix --dry-run

# Apply fixes for all recorded warnings:
php artisan nplusone:autofix

# Fix a single warning by id:
php artisan nplusone:autofix --id=42

# Override the model for this run:
php artisan nplusone:autofix --model=claude-opus-4-8

# Warnings recorded on another host (e.g. production paths like
# /var/www/html/...) are re-anchored on your local project root. Point at a
# different root if needed:
php artisan nplusone:autofix --base-path=/home/me/project

For each warning the command:

  1. Resolves the stored location to a readable local file (remapping foreign absolute paths onto your project root via the configured source_roots).
  2. Sends the SQL, location, and a ±60-line source window to Claude, which returns a { file, search, replace, explanation } patch (or aborts).
  3. Verifies the search text exists and is unique, then applies it. A non-unique or missing search is skipped for safety.
  4. Deletes the warning row once the file is patched.

--dry-run prints the search/replace pair and writes nothing.

Testing

composer install
composer test   # or: ./vendor/bin/pest

License

MIT