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
This page is the working piece. The full pack has everything below.
The Livewire 2 lines that die quietly in Livewire 3 — named, with the v3 replacement beside each
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.