⚠️ Experimental. mir is under active development and not yet production-ready. APIs, CLI flags, issue codes, and output formats may change between releases; expect false positives and rough edges.
A fast, incremental PHP static analyzer written in Rust, inspired by Psalm.
- 77 diagnostic rules across type errors, undefined symbols, dead code, taint, and more
- Sound type system — scalars, objects, generics, unions, intersections, literals,
never,void - Full type inference — return types, literal narrowing,
if/match/instanceof/is_string()etc. - Call checking — argument count and types for user-defined and built-in functions/methods
- Class analysis — inheritance, interface compliance, abstract enforcement, visibility,
readonly,final - Dead code detection — unused variables, parameters, private methods, properties, and functions
- Taint analysis — tracks data from
$_GET/$_POSTto HTML/SQL/shell sinks - Incremental cache — unchanged files skipped on re-runs via SHA-256 content hashing
- Parallel analysis — rayon-powered; scales to available CPUs
- PHP 7.4–8.5 support with version-aware stub filtering
- Comprehensive built-in coverage — powered by JetBrains phpstorm-stubs (57 extensions, 500+ functions, 100+ classes)
composer require --dev miropen/mir-php
vendor/bin/mir src/A post-install-cmd hook downloads the prebuilt binary matching your version
and host platform from GitHub Releases. See
docs/getting-started.md for supported
targets.
cargo install mir-phpgit clone https://github.com/jorgsowa/mir.git
cd mir
cargo build --release
# binary at target/release/mirmir # analyze current directory
mir src/ lib/ # analyze specific paths
mir --format json src/ # machine-readable output
mir --baseline baseline.xml src/ # suppress known issuesSee docs/cli.md for the full CLI reference.
Silence a single false positive directly in the source with a comment, without editing config or a baseline file:
// @mir-ignore UndefinedClass
new ThirdPartyClass();
$obj->method(); // @mir-ignore NullMethodCall (trailing: this line)
// @mir-ignore-next-line PossiblyNullArgument
doThing($maybeNull);A bare comment above a statement annotates the statement that follows it; a
trailing comment annotates its own line. List one or more IssueKind names (or
codes such as MIR1400) after the directive, or omit them to suppress every
issue on the target line. @mir-ignore-file Kind … suppresses a kind across the
whole file. The @psalm-suppress, @suppress, @phpstan-ignore-line and
@phpstan-ignore-next-line aliases are accepted for drop-in compatibility.
Directives are matched per physical line, so a directive written inside a string literal or heredoc body is also honored — harmless in practice, since no diagnostic is normally reported on such a line.
Full documentation is available at jorgsowa.github.io/mir.
See CONTRIBUTING.md.
MIT