laravel/lsp
Laravel LSP adds framework-aware editor support for Laravel and Blade, with completions, hovers, diagnostics, document links, Go to Definition, and code actions across routes, views, translations, config, and env vars. Install globally via Composer and launch over stdio from your project root.
Developer Experience as a Platform Investment
Laravel LSP is a zero-cost, zero-footprint lever for improving engineering throughput. Because it installs globally via Composer and never enters a project's composer.json, it requires no dependency review, no lockfile churn, no security sign-off on production artifacts, and no rollback plan. A PM can treat adoption as a trialable DX experiment rather than a platform migration — the cost of trying it is a single command per developer, and the cost of abandoning it is deleting that command.
Concrete decisions this informs:
view('dashboard.index'), route('users.show'), config('services.stripe.key'), __('auth.failed'), env('DB_HOST'), Blade component names, Livewire components, Inertia pages, middleware aliases, storage disks, container bindings, validation rules, controller actions — all of these are strings whose correctness no PHP type system enforces. LSP turns them into navigable, diagnosed references. That is a defensible reason to deprioritize an in-house equivalent.docs/editor.md (global install line + the two or three editor configs the team actually uses + a restart instruction) and let developers stay in their preferred tool. Mandating VS Code to obtain these features would forfeit the package's main advantage.phpEnvironment option (auto, herd, valet, sail, lando, ddev, local) with the phpCommand override is a diagnostic instrument disguised as a config flag. If most of the team must pin phpCommand to ["./vendor/bin/sail", "php"] to make indexing work, that is evidence your local-dev story is inconsistent. Treat recurring overrides as a signal to converge on one blessed environment rather than a per-developer workaround to document. Conversely, teams already on Sail or DDEV can ship a config that just works.true and can be turned off individually. This makes staged rollout possible per repo — start with routes, views, config, translations, env (highest-value, lowest-noise) and add Eloquent/Livewire/Inertia as confidence grows. It also lets you suppress noise in repos with heavy dynamic usage.artisan, so "open the project root" is a hard operational requirement. If your repo layout is a monorepo with several Laravel apps or a container-mounted tree, that constraint is a real adoption blocker you can decide on up front, not discover mid-rollout.Good fit when:
PATH.Look elsewhere or wait when:
artisan. Monorepo roots, nested apps, or heavily containerized mounts will need per-app editor config or won't attach at all.config($someVariable), generated view names). Static analysis can't resolve those; diagnostics may be noisy or silent. Use per-feature flags to mute them.Suggested adoption gate: pick one Laravel repo and three to five volunteers across at least two editors. Success criteria — the five canonical jumps resolve (view, route, config, __, env), a deliberately broken view('does.not.exist') produces a diagnostic, and Blade definition/code actions work. If those hold, expand per repo with the onboarding doc; if not, the failure is localized and cheap to reverse.
For executives (one paragraph): Laravel LSP is an official, open-source (MIT) language server that makes our editor understand Laravel. It adds autocomplete, hover documentation, error highlighting, and click-through navigation for the parts of Laravel that are written as plain strings — route names, view names, translation keys, config keys, environment variables, Blade and Livewire components, Inertia pages. Today those mistakes are caught late, in QA or production. With this, they're caught while typing. It installs in one command on each developer's machine, adds nothing to our application code or deployment, needs no new budget, and works across the editors our team already uses. We propose a small pilot on one repository before any broader rollout.
For engineering leaders:
No dependency footprint and no CI change — it's a globally installed developer binary, not a project package. Zero production risk. Adoption is reversible in one command. Expected outcomes are fewer trivial runtime failures from stale strings, faster onboarding to Laravel conventions, and editor-level consistency without an editor mandate. Cost is a one-time onboarding step per developer plus a short per-repo docs/editor.md.
For engineers:
It closes the gap generic PHP tooling leaves open. Go to Definition on view('dashboard.index') lands on the Blade file; hover on route('users.show', $user) shows the URI and verb; config(...), __(...), and env(...) jump to their sources; Blade and Livewire get completion and diagnostics; a typo'd view name gets flagged immediately instead of at runtime. Keep your current editor — official clients exist for VS Code, Cursor, Zed, and Sublime, and documented setup for Neovim 0.11+ and OpenCode. Three things to know: install globally with composer global require laravel/lsp and make sure Composer's global bin is on PATH; always open the Laravel project root (it finds the app via artisan); and restart your editor after configuring. If you use Sail, Lando, DDEV, Herd, or Valet, set phpEnvironment or phpCommand so indexing uses the right PHP runtime.
Anticipated objections:
artisan. We scope the pilot to standard single-app repos and revisit monorepo support separately.How can I help you explore Laravel packages today?