Skip to content

Getting Started

This guide walks you through installing mir, running your first analysis, and understanding the results.

Section titled “From Composer (recommended for PHP projects)”
Terminal window
composer require --dev miropen/mir-php

The package is a thin wrapper: a post-install-cmd hook downloads the prebuilt mir binary that matches the installed version and host platform from GitHub Releases, verifies its SHA-256 checksum, and places it at vendor/miropen/mir-php/bin/mir. Composer exposes it as vendor/bin/mir:

Terminal window
vendor/bin/mir src/

Prebuilt binaries are published for x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, x86_64-apple-darwin, aarch64-apple-darwin, and x86_64-pc-windows-msvc. On other platforms install with cargo or build from source.

Terminal window
cargo install mir-php
Terminal window
git clone https://github.com/jorgsowa/mir.git
cd mir
cargo build --release
# Binary is at target/release/mir

You can then copy the binary to a directory on your $PATH:

Terminal window
cp target/release/mir ~/.local/bin/

Point mir at one or more directories containing PHP source files:

Terminal window
mir src/

You can pass multiple paths:

Terminal window
mir application/library application/module public/

mir will recursively scan all .php files under the given paths and print any issues to stdout.

If your project targets a specific PHP version, pass --php-version:

Terminal window
mir --php-version 8.2 src/

By default mir uses all available CPU cores. To limit parallelism:

Terminal window
mir -j 4 src/

Each issue is printed on one line with the format:

path/to/file.php:LINE:COL IssueKind message

For example:

src/Controller/UserController.php:42:5 UndefinedMethod Method User::getName() does not exist
src/Service/Mailer.php:17:12 InvalidArgument Argument 1 of sendMessage expects string, int provided

A non-zero exit code (1) means at least one issue was found; exit code 0 means the analysis is clean.

The most common issue kinds you will encounter:

KindWhat it means
UndefinedVariableA variable is used before it is assigned
UndefinedFunctionA function call that has no definition
UndefinedMethodA method call on a type that does not have that method
UndefinedClassA class / interface / trait that does not exist
InvalidArgumentA value passed to a function does not match the declared type
InvalidReturnTypeA function returns a type that does not match its declaration
PossiblyInvalidArrayAccessArray access on a value that may be false or null
NullableReturnStatementA nullable value returned from a non-nullable return type

See Issue Kinds for the full list.

mir auto-discovers mir.xml or psalm.xml in the project root. You can also specify a config file explicitly:

Terminal window
mir -c psalm.xml src/

On large projects you may want to introduce mir without fixing every pre-existing issue at once. Generate a baseline file that records all current issues:

Terminal window
mir --set-baseline psalm-baseline.xml src/

On subsequent runs, pass the baseline to suppress those issues and only report new ones:

Terminal window
mir --baseline psalm-baseline.xml src/

When you fix issues, shrink the baseline so they are not re-introduced:

Terminal window
mir --update-baseline --baseline psalm-baseline.xml src/

mir supports several output formats suited to CI environments:

Terminal window
# GitHub Actions inline annotations
mir --format github --no-progress src/
# JUnit XML (compatible with most CI systems)
mir --format junit src/ > results.xml
# SARIF (GitHub Code Scanning / VS Code)
mir --format sarif src/ > results.sarif

For large codebases, enable the incremental cache to speed up repeated runs:

Terminal window
mir --cache-dir .mir-cache src/

See the CLI Reference for the full list of options and the Docblock Annotations page for how to annotate your PHP code with type information.