NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Packagist · #506 most downloaded on Packagist
A static analysis tool for finding errors in PHP applications
Last release today
07 Oct 2026
Ships unpredictably
gaps range from 8 days to 5 months
Rarely documented
notes for 12 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
10 years old
498 releases · first in 2016
Taint what functions and builtins leave in by-reference parameters by @danog in #12095
Full Changelog: 7.0.0-beta24...7.0.0-rc1
One column per quarter.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Purity and taint fixes: getters, explicit/overridden annotations, defaults, void templates, ext stubs, socket builtins by @danog in #12073
Full Changelog: 7.0.0-beta23...7.0.0-beta24
Report string increments as deprecated since PHP 8.5, suggest str_increment() by @danog in #11993
@self-out / @this-out by @alies-dev in #11964@param-closure-this docblock tag by @alies-dev in #11853#[\Override] on properties (PHP 8.5) by @alies-dev in #11891IdeDetector, auto-detect IDE when none specified by @alies-dev in #11802--init-ci command to generate GitHub Actions workflow by @alies-dev in #11748extraFiles also for language server by @susnux in #11919clone() withProperties keys by @alies-dev in #11999_ purity of closure types as a class name by @danog in #12014$class::$prop reads and assignments when the class is a variable by @HenkPoley in #12040new $c checks when the class string has a leading backslash by @HenkPoley in #12039_ purity by @danog in #12043TypeParseTreeException for an incomplete conditional type by @alies-dev in #11962TKeyedArray::make() factory to 6.x for cross-version plugin compatibility by @alies-dev in #11810Full Changelog: 7.0.0-beta22...7.0.0-beta23
[6.x] Support the PHP 8.5 #[\NoDiscard] attribute by @alies-dev in #11892
#[\NoDiscard] attribute by @alies-dev in #11892trace key to error_get_last() by @janedbal in #11975self in @property type tokens at scan time by @alies-dev in #11846Full Changelog: 7.0.0-beta21...7.0.0-beta22
Restore custom taint map from cache; make taint analysis deterministic by @danog in #11946
Full Changelog: 7.0.0-beta20...7.0.0-beta21
Rewrite dead-code detection on a code-use graph and infer purity across the call graph. Unused-code detection now runs on a directed graph of referenc
Psalm\Internal\Codebase\CodeUseGraph), in the same way as taint analysis:MissingPureAnnotation (and its --alter--find-unused-psalm-suppress now also reports redundant @psalm-suppress on--taint-analysis, on Tainted* issues.@api. @danog in #11939IncompatibleTypeParameters issue (level 1),echo/print/exit taint sinks not matching their argument nodes (which brokeTaintedHtml detection through those constructs), fix taint tracking throughDataFlowNode factories$this failing to parse inside generic type parameterscovariant/contravariant variance modifiers in generic typeUndefinedDocblockClass (backport)TLiteralFloat now renders NAN values as float(NAN) in--find-unused-psalm-suppress checking in docs/running_psalm/configuration.md,docs/annotating_code/supported_annotations.md,docs/running_psalm/issues/MissingPureAnnotation.md anddocs/running_psalm/issues/UnusedPsalmSuppress.md, and update the CLI helpdocs/annotating_code/type_variables.md and the IncompatibleTypeParametersDataFlowNode factories: mandatory $storage, typed callable kinds,ScopeAnalyzergetArgs() callsOverride in the SuicidalAutoloader fixture and dropimpure- Closure prefix in TypeParseTestsebastian/diff 9Full Changelog: 7.0.0-beta19...7.0.0-beta20
Nothing published for this version
Final improvements for reduced scanning by @danog in #11809
Full Changelog: 7.0.0-beta18...7.0.0-beta19
Introduce psalm plugin API by @danog in #11739
compact output format to table, add new truly compact format by @alies-dev in #11750TaintedLlmPrompt issue type for prompt injection detection by @alies-dev in #11746ERROR_LEVEL for plugin-defined issues by @alies-dev in #11736PHPSTORM env var on Darwin by @alies-dev in #11801Full Changelog: 7.0.0-beta17...7.0.0-beta18
Add stub for memcached by @ADmad in #11717
Full Changelog: 7.0.0-beta16...7.0.0-beta17
This release allows using @psalm-pure on classes, which will mark all methods as pure, and ban property declarations.
This release allows using @psalm-pure on classes, which will mark all methods as pure, and ban property declarations.
Full Changelog: 7.0.0-beta15...7.0.0-beta16
This release features a major refactoring of Psalm's mutability inference system.
This release features a major refactoring of Psalm's mutability inference system.
This release will likely be followed by a stable release.
The new automated mutability (pure, mutation free, externally mutation free, impure) attribute fixes that will be proposed by Psalm, when applied, will improve Psalm's type inference and especially security analysis, as pure functions are automatically specialized by Psalm, killing false positives during security analysis.
Now, Psalm will always analyze and emit MissingPureAnnotation and MissingImmutableAnnotation issues for all functions, methods and classes that can be marked with one of the following attributes (which can be automatically added by running Psalm with --alter --issues=MissingPureAnnotation,MissingImmutableAnnotation).
For functions and methods, MissingPureAnnotation will be emitted, automatically adding the following annotations:
@psalm-pure » - Indicates that the function or method is pure, one whose output is just a function of its input (no mutations or even read property accesses allowed).@psalm-mutation-free » - Used to annotate a class method that does not mutate state, either internally or externally of the class's scope (only internal property reads on $this are allowed for methods)@psalm-external-mutation-free » - Used to annotate a class method that does not mutate state externally of the class's scope (internal property reads and writes on $this and self are allowed for methods)@psalm-impure » - A new annotation, equivalent to the default mutability level of functions and methods (all mutations allowed): Psalm will require the explicit annotation of only abstract methods with this or any of the above annotations through a separate, non-autofixable MissingAbstractPureAnnotation issue, to improve mutability inference for implementors of an interface (though it can be used on all functions and methods as well).For classes, MissingImmutableAnnotation will be emitted, automatically adding the following annotations:
@psalm-immutable » - Used to annotate a class where every property is treated by consumers as @psalm-readonly and every instance method is treated as @psalm-mutation-free.@psalm-external-mutation-free » - Used to annotate a class where every instance method is treated as @psalm-external-mutation-free.@psalm-mutable » - A new annotation, used to annotate a class where at least one property is mutable: this is the default behavior, but it can be explicitly marked for clarity: Psalm will require the explicit annotation of only interfaces with this or any of the above annotations through a separate, non-autofixable MissingInterfaceImmutableAnnotation issue, to improve mutability inference for implementors of an interface (though it can be used on all classes and interfaces as well).For situations where the callable or Closure needs to be pure, mutation-free or externally mutation-free, the following subtypes are available:
@psalm-pure
pure-callablepure-Closure$this are allowed for methods), equivalent to marking functions or methods with @psalm-mutation-free
self-accessing-callableself-accessing-Closure$this and self are allowed for methods), equivalent to marking functions or methods with @psalm-external-mutation-free
self-mutating-callableself-mutating-Closure@psalm-impure
impure-callable (an alias to callable)impure-Closure (an alias to Closure)This can be useful when the callable is used in a function marked with @psalm-pure or @psalm-mutation-free or @psalm-external-mutation-free.
Full Changelog: 6.15.1...7.0.0-beta15
More detailed progress for taint graph resolution by @danog in #11349
--config= cli parameter by @ThomasLandauer in #11332Full Changelog: 6.14.3...7.0.0-beta14
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
[6.x] Report string increments as deprecated since PHP 8.5 (backport) by @alies-dev in #12062
parent:: first-class callables of @method pseudo-methods by @alies-dev in #12148Full Changelog: 6.19.1...6.19.2
Keep polyfills of newer native functions out of the global functions on cached runs by @danog in #12025
$class::$prop reads and assignments when the class is a variable by @HenkPoley in #12040new $c checks when the class string has a leading backslash by @HenkPoley in #12039Full Changelog: 6.19.0...6.19.1
[6.x] Support @param-closure-this docblock tag by @alies-dev in #11853
@param-closure-this docblock tag by @alies-dev in #11853#[\Override] on properties (PHP 8.5) by @alies-dev in #11891IdeDetector, auto-detect IDE when none specified by @alies-dev in #11802extraFiles also for language server by @susnux in #11919clone() withProperties keys by @alies-dev in #11999TKeyedArray::make() factory to 6.x for cross-version plugin compatibility by @alies-dev in #11810Full Changelog: 6.18.1...6.19.0
Emit issues on php <8.5 if overridden method uses self instead of static by @danog in #11985
@self-out / @this-out by @alies-dev in #11964TypeParseTreeException for an incomplete conditional type by @alies-dev in #11962Full Changelog: 6.18.0...6.18.1
[6.x] Support the PHP 8.5 #[\NoDiscard] attribute by @alies-dev in #11892
#[\NoDiscard] attribute by @alies-dev in #11892trace key to error_get_last() by @janedbal in #11975self in @property type tokens at scan time by @alies-dev in #11846Full Changelog: 6.17.2...6.18.0
Fix function manipulator by @danog in #11671
Full Changelog: 6.17.1...6.17.2
What's Changed Fixes Fix #11937 by @danog in #11938 Full Changelog : 6.17.0...6.17.1
Support better template inference with type variables: class templates that cannot be inferred at the construction site are now tracked as type variab
new Box(1) followed by $box->set('two') under @template T of int|string) and introduces the new IncompatibleTypeParameters issue (level 1), documented in https://psalm.dev/docs/annotating_code/type_variables/ by @muglug in #11875$this failing to parse inside generic type parameters by @alies-dev in #11768PHPSTORM env var on Darwin by @alies-dev in #11801covariant/contravariant keywords in generic type parameters instead of reporting UndefinedDocblockClass (backport) by @alies-dev in #11836TLiteralFloat now renders NAN values as float(NAN) in type keys and IDs instead of crashing by @danog in 9d6db9e and ca15124docs/annotating_code/type_variables.md and the IncompatibleTypeParameters issue page by @muglug in #11875impure- Closure prefix in TypeParseTest by @alies-dev in #11834Override in SuicidalAutoloader fixture by @alies-dev in #11835test-with-real-projects.sh on macOS (use gsed when available, tolerate a missing phar) by @danog in 9d6db9evoidParamType test: nikic/php-parser 5.8 rejects void params at parse time by @danog in 056992a90Full Changelog: 6.16.1...6.17.0
Fix --show-snippet option silently consuming next CLI argument by @alies-dev in #11684
Full Changelog: 6.16.0...6.16.1
Add stub for memcached by @ADmad in #11717
Full Changelog: 6.15.1...6.16.0
Allow sebastian/diff 8 by @Jean85 in #11667
Note: GPG signatures for older releases will be regenerated shortly using the new 99BF4D9A33D65E1E key, since the old one expired.
Note: GPG signatures for older releases will be regenerated shortly using the new 99BF4D9A33D65E1E key, since the old one expired.
Full Changelog: 6.14.3...6.15.0
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →