Tech 4 min read

Trying Claude Code v2.0.74's LSP Feature with PHP — It's a Known Bug

Claude Code v2.0.74 shipped with LSP (Language Server Protocol) support, so I tried it in a PHP environment. The short answer: it didn’t work — but digging into it revealed the issue is a known bug. Here’s the investigation.

What LSP Support Means

LSP is the protocol that powers code completion, go-to-definition, and similar IDE features. The v2.0.74 release notes listed three new capabilities:

  • go-to-definition — jump to where something is defined
  • find references — locate all usages
  • hover documentation — show docs on hover

With this working, Claude Code could understand codebases more precisely — using type information rather than grep for more accurate analysis.

Test Environment

  • Windows 11
  • PHP 8.3.27
  • Composer 2.9.1
  • Claude Code 2.0.74

phpactor → Failed

First attempt: phpactor, a PHP LSP server.

composer global require phpactor/phpactor

Result:

Your requirements could not be resolved to an installable set of packages.

Problem 1
  - phpactor/phpactor requires ext-pcntl * -> it is missing from your system.

ext-pcntl is a Unix process control extension — not available on Windows.

WSL (Ubuntu 22.04) is installed, which would technically work, but I use Docker for development. Setting up a Docker environment just to test Claude Code’s LSP integration felt like too much overhead. Skipped both options.

intelephense → Installed, Not Recognized

Next: intelephense, a Node.js-based PHP LSP server.

npm install -g intelephense

Install succeeded. Created a test PHP project and tried it in Claude Code.

Test 1: Specify directory in the prompt

In the php-lsp-test folder, jump to the definition of UserService inside UserController

Test 2: Open folder first, then prompt

Open the php-lsp-test folder in a new VS Code window, then give the instruction.

Jump to the definition of UserService inside UserController

Result: LSP wasn’t used in either case. Claude Code fell back to Glob + Read for file searching.

Specifically, it did this:

Glob pattern: "**/*.php"
Found 4 files
Read src/Controller/UserController.php
Read src/Service/UserService.php

If LSP go-to-definition had worked, it would jump directly to the definition without listing files first. Instead, it enumerated files with Glob, read them with Read, and searched for the definition as text. Same behavior as before LSP support existed.

Checking the Settings

There was a mention of an --enable-lsp-logging flag — tried it:

claude --enable-lsp-logging
error: unknown option '--enable-lsp-logging'

Doesn’t exist.

Found the GitHub Issue

Searching turned up Issue #14803, filed on 2025-12-20 — the day before I tested.

Root Cause

Race condition — the LSP Manager initializes before plugins finish loading.

Debug log:

LSP notification handlers registered for 0 servers
(52ms later)
Plugin loading begins...

At initialization time, no plugins are loaded yet, so the LSP Manager sees “available LSP servers: 0.”

Regression

  • Working in v2.0.67
  • Broken since v2.0.69

Issue status: OPEN (unresolved).

Verification Summary

ItemResult
phpactor installationFailed — requires ext-pcntl, not available on Windows
intelephense installationSucceeded
LSP usage in Claude CodeNot recognized (falls back to Glob + Read)
--enable-lsp-logging flagUnknown option
Root causeIssue #14803 (race condition)

Takeaway

Rushing to try a new feature is fine, but features this early in development may still be broken. Checking GitHub Issues first would have saved a wasted run. That said, actually going through “doesn’t work → why? → found the issue” was a worthwhile exercise.

Next Steps

No matter how well-documented a codebase is or how decoupled it is through DI, “where exactly is this method called from?” always gets murky. LSP find references would let Claude Code trace calls accurately. Looking forward to it working properly — will test again once the fix lands.