Finds Livewire 2 APIs that silently die in Livewire 3 — emit(), wire:model.defer, dispatchBrowserEvent, livewire:load, missing :key — in your .php and .blade.php files. Runs entirely in your browser — nothing is uploaded.
Same engine as the VS Code extension, byte for byte.
Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.
VS Code MarketplaceOpen VSX (Cursor, VSCodium)npmMCP server (npx)Docker Hubext install ReadyStack.livewire3-upgrade-blocker-lint npx @readystack/livewire3-upgrade-blocker-lint <file> npx @readystack/livewire3-upgrade-blocker-lint --mcp
Team? One key for every ReadyStack linter, 5 seats, $149 once
Scan every .php and .blade.php in the workspace in one command and export an owned REPORT.md / JSON with file:line for the whole migration, plus a non-zero exit code for CI.
One payment, one licence key for this tool. The key is shown right after payment.
A freelance Laravel developer at $85/hour spends the opening hours of an upgrade making this inventory by hand
Buy the full version — $29· ReadyStack
Real numbers from this tool, line by line.

Fourteen blockers - 10 errors and 4 warnings - inside one 43-line Livewire 2 component: that is what a Laravel developer maintaining a Livewire 2 app sees on the very first file this linter reads. Audited 2026-09-18, the same component rewritten for Livewire 3 reports zero.
That number is invisible without a tool because of the shape of the break. It is not a build failure: Blade compiles, the page renders, the layout is identical - and then a button does nothing and a search box stops filtering.
Four of the fourteen are event calls. $this->emit('invoiceSaved') is gone in Livewire 3; the method name is dispatch. PHP does not care until that line executes, so the failure waits for whichever user presses Save first. $this->emitTo('billing.totals', 'refresh') becomes $this->dispatch('refresh')->to(...). emitUp and emitSelf are gone too - events bubble by default - and dispatchBrowserEvent folds into the same dispatch.
Six are in the template, and these are the quiet ones. wire:model.defer is not an error in Livewire 3 - plain wire:model is already deferred, so the modifier is simply ignored. wire:model.lazy became wire:model.blur. wire:model.debounce.400ms is the worst of the set: debounce now applies only to live bindings, so without .live the input sends nothing at all and the field looks like a plain text box. wire:click.prefetch has no replacement, @livewireStyles is gone, and livewire:load is now livewire:init - so every Alpine component registered inside that listener silently never initialises.
The last five sit on the component surface. protected $queryString is replaced by the #[Url] attribute per property, so the array is read as an ordinary property and the URL quietly stops syncing. Livewire 3 discovers components in App\Livewire, not App\Http\Livewire, and the .defer suffix on $wire.entangle() is gone. assertEmitted is now assertDispatched, so a test on the old name fails as an undefined method - a green suite that never checked the event. And a <livewire:row> tag inside @foreach now needs :key; without it the DOM diff reuses the wrong child component, so after a delete row 3's state appears on row 4.
That last rule is why grep -r "emit(" is not the answer: the defect is not a string that is present but an attribute that is absent inside a block, which needs the loop depth a line-oriented search never tracks. Same for debounce: wire:model.debounce is dead, wire:model.live.debounce is correct, and one is a prefix of the other.
Staying put is not a neutral option. Livewire 2 caps the application at Laravel 10, whose security support ended 2025-02-04. Every month on v2 is a month on an unsupported framework version, and the list above is the toll booth.
The extension is 15 rules over **/*.php, which includes .blade.php. Blade {{-- --}} and PHP comments are stripped before matching, so a migration note mentioning emit() is not reported, and the matching is local. Free: the file you have open, every blocker with its v3 replacement, no watermark and no run cap. Paid, a different axis: every .php and .blade.php in the workspace in one command, exported as a REPORT.md or JSON with file:line you keep, plus a non-zero exit code for CI.
A freelance Laravel developer at $85 an hour spends the opening hours of any upgrade building this inventory by hand. The same engine, the same rules.json, also runs on one browser page with nothing installed - paste a component, read the fourteen.
It reads your .php and .blade.php files and flags the Livewire 2 lines that stop working under Livewire 3, printing the v3 replacement next to each one. Fifteen rules cover events, Blade modifiers and the component surface. On the 43-line Livewire 2 component shipped with it, the engine reports 14 blockers: 10 errors and 4 warnings.
Laravel developers who own an app still running Livewire 2 and are doing, planning or reviewing the move to Livewire 3 — including anyone reviewing Livewire code an assistant generated, which is often written against the Livewire 2 API. Agencies inheriting a client Laravel app use it as the first pass before quoting the upgrade.
Grep finds emit( and wire:model.defer. It cannot find a <livewire:row> inside @foreach that is missing :key, because that defect is a missing attribute inside a block and needs loop depth. It also cannot separate wire:model.debounce, which is dead in v3, from wire:model.live.debounce, which is correct, since one string contains the other.
Free and unlimited: scan the file you have open and get every blocker with its Livewire 3 replacement, line by line. That finishes that file, with no watermark and no run cap. The licence key adds a different job: scanning every .php and .blade.php in the workspace at once and exporting a REPORT.md or JSON with file:line, plus a CI exit code.
A freelance Laravel developer at $85 an hour spends the first hours of any Livewire upgrade making exactly this inventory by hand, component by component. The extension is $29 once, with one licence key per person or team seat and. The free tier covers a single file without paying anything.
A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. Livewire 3 Upgrade Blocker Lint checks the file you open against 15 rules from a rule set dated 2026-09-20, and points at the exact line with the fix. For a filing, an audit or a client you need that dated result on your own files.
One question, answered by the person who built it. Your email only if you want the answer sent.
Paste this code into your page. It runs in your visitor’s browser and stays up to date. Nothing your visitors type is stored.
For businesses: your name and logo instead of ours, and each visitor’s result + e-mail in your inbox (only when they tick consent) — Pro from $19/month. See Pro →