PHPStan: clickable file paths in the terminal via phpstan.neon


Suppose your PHP/Laravel project has a structure like this:

.
├── artisan
├── (...)
├── routes
├── src
│   ├── App
│   └── Domain
├── (...)
├── vendor
└── vite.config.js

You’re running PHPStan in the terminal and, when it analyses your code, errors look like this:

 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  Line   App/Concerns/PasswordValidationRules.php (in context of class App\Actions\Fortify\CreateNewUser)
 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  17     Method App\Actions\Fortify\CreateNewUser::passwordRules() should return array<int, array<mixed>|Illuminate\Contracts\Validation\ValidationRule|string> but returns
          array<int, Illuminate\Validation\Rules\Password|string>.
         🪪  return.type
 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------

The paths look correct at first glance, but they are actually incomplete: the leading segment that anchors them to the project root is missing. Terminals like iTerm2, or the integrated terminal in PhpStorm and VS Code, can only make a relative path correctly clickable when it is complete relative to the project root. In this case, the correct filesystem path is src/App/Concerns/PasswordValidationRules.php. With a truncated path like App/Concerns/PasswordValidationRules.php, the terminal cannot locate the file or resolves the link incorrectly.

In my case (using iTerm2 on macOS), when I press CMD and click the link, it is interpreted as an http:// address and opened in the browser (which has no idea what to do with it).

Why does this happen?

If your phpstan.neon looks like this:

parameters:

  paths:
    - src

…then PHPStan reports error paths relative to that single subdirectory, making them incomplete:

The path App/Concerns/PasswordValidationRules.php is relative to src, not to the project root. The terminal cannot resolve it and the link does not work.

The fix

The simplest approach is to list two or more paths under the paths key in phpstan.neon:

parameters:
  paths:
    - src
    - tests

Errors will then be reported with complete paths relative to the root:

 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  Line   src/App/Concerns/PasswordValidationRules.php (in context of class App\Actions\Fortify\CreateNewUser)
 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  17     Method App\Actions\Fortify\CreateNewUser::passwordRules() should return array<int, array<mixed>|Illuminate\Contracts\Validation\ValidationRule|string> but returns
          array<int, Illuminate\Validation\Rules\Password|string>.
         🪪  return.type
 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------

The path src/App/Concerns/PasswordValidationRules.php is now complete and clickable: a single click opens the file at the exact line in your IDE.

Alternative solution

What if you have a reason to scan only one directory (e.g. src)?

Add this block to phpstan.neon:

services:
  relativePathHelper:
    class: PHPStan\File\SimpleRelativePathHelper
    arguments:
      currentWorkingDirectory: %currentWorkingDirectory%

Conclusion

A small misconfiguration in phpstan.neon is enough to make error paths unusable in the terminal. With the right configuration, paths will be complete and clickable, letting you navigate straight to the problem with a single click.

Better Developer eXperience = happier developer 😄