AI × Tools & Tips

Tools · Setup guide

Laravel LSP

Laravel's first-party language server — it gives any LSP-capable editor the route, view, config, and Blade autocomplete that used to be VS Code only.

Laravel LSP

Before you start

Set it up

  1. Install the server globally:

    shell
    composer global require laravel/lsp
  2. Confirm Composer's global bin directory is on your PATH. Get the exact path for your machine — don't guess it:

    shell
    composer global config bin-dir --absolute

    On macOS this typically prints /Users/<you>/.composer/vendor/bin. If it isn't on your PATH, add it to ~/.zshrc:

    shell
    export PATH="$HOME/.composer/vendor/bin:$PATH"
  3. Verify the binary runs:

    shell
    laravel-lsp --version

    Verified output:

    terminal
    Laravel LSP v0.0.29
  4. Point your editor at it. If your editor has an official extension, install that instead of configuring the server by hand — the extension manages the server process for you.

    Editor How
    VS Code Laravel VS Code extension
    Cursor Same VS Code extension — it's compatible
    Sublime Text Laravel Sublime Text extension
    Zed Laravel Zed extension
    Neovim Manual config, below
    OpenCode Manual config, below

    Neovim (0.11+ required):

    lua
    vim.lsp.config("laravel_lsp", {
        cmd = { "laravel-lsp" },
        filetypes = { "php", "blade" },
        root_markers = { "artisan", "composer.json", ".git" },
    })
    
    vim.lsp.enable("laravel_lsp")

    OpenCode — in opencode.json:

    json
    {
        "$schema": "https://opencode.ai/config.json",
        "lsp": {
            "laravel-lsp": {
                "command": ["laravel-lsp"],
                "extensions": [".php", ".blade.php"]
            }
        }
    }
  5. If your PHP isn't being found, tell the server which environment to use. Options are passed through your editor's LSP initializationOptions. phpEnvironment defaults to auto, which tries Herd, Valet, Sail, Lando, DDEV, then local PHP:

    json
    { "phpEnvironment": "herd" }

    Accepted values: auto, herd, valet, sail, lando, ddev, local. For anything unusual, set an explicit command instead — it takes precedence over phpEnvironment:

    json
    { "phpCommand": ["./vendor/bin/sail", "php"] }

What success looks like

Open a Laravel project and you should get completions inside string literals — type route(' or config(' or view(' and see your app's actual route names, config keys, and view paths. Hover a route name for its URI. Broken references get squiggled as diagnostics, and cmd-click jumps to the definition.

The server advertises these capabilities on connect (verified against a real Laravel 13.23.0 app):

terminal
codeActionProvider, completionProvider, definitionProvider,
documentLinkProvider, hoverProvider, textDocumentSync

Completion fires on these trigger characters: " ' . | x - : @ — the x and - are there to catch Blade components like <x-button-primary>.

Coverage spans routes, views and Blade, translations, config, environment variables, assets and Mix, middleware, Inertia, Livewire components, auth and policies, container bindings, validation rules, controller actions, and Eloquent.

Tuning it

Every feature is a boolean that defaults to true, named {feature}{Capability} — so routeCompletion, routeDiagnostics, routeHover, routeLink, and the same pattern for config, view, env, middleware, inertia, translation, asset, auth, appBinding, storage, mix, bladeComponent, and controllerAction. Set one to false to switch it off.

If diagnostics get noisy on a legacy codebase, turning off just routeDiagnostics and viewDiagnostics keeps the completions while dropping the warnings.

Using Pest? pestGenerateDocBlocks (default true) writes and maintains helper docblocks at storage/framework/testing/_pest.php, configurable via pestHelperFilePath.

Verified vs not

Verified: laravel/lsp v0.0.29 exists on Packagist (27 releases, requires php ^8.2.0), installs cleanly via Composer, ships a working laravel-lsp executable, reports Laravel LSP v0.0.29, and completes a real LSP initialize handshake against a Laravel 13.23.0 app returning the capabilities listed above. Every editor and repo link was confirmed to resolve.

Not simulated: installing or using any of the editor extensions (VS Code, Cursor, Sublime, Zed), the Neovim and OpenCode configs, and the actual in-editor completion experience. The install was also verified as a project-local dependency rather than composer global to avoid modifying a global Composer setup — the command above is the one from the official README.

One nuance: the README describes "prebuilt binaries" per platform, but what ships in vendor/bin is a ~27 MB self-contained PHP script, which is why PHP 8.2+ is a hard requirement rather than just a build-time one.

Go deeper