# Qualimetrix — Full Documentation > This file is auto-generated from the website documentation. > It contains the complete reference for Qualimetrix in a single file, > optimized for consumption by LLMs and AI coding agents. > > For a concise overview, see llms.txt instead. > For human-readable documentation, visit https://qualimetrix.github.io/qualimetrix/ ## Table of Contents - Home - Getting Started - Installation - Quick Start - Configuration - Usage - Usage Scenarios - CLI Options - Git Integration - Baseline - Output Formats - Rules - Overview - Complexity - Coupling - Size - Maintainability - Cohesion - Design - Architecture - Duplication - Code Smells - Security - Guides - Architecture Investigation - CI/CD Integration - GitHub Actions - Other CI Systems - Reference - Default Thresholds - Health Scores # Qualimetrix **Fast PHP static analysis tool** focused on code quality metrics, complexity analysis, and architectural insights. ## Why Qualimetrix? - **Fast** — 9x faster than phpmd in sequential mode, up to 39x with parallel workers - **Deep OOP metrics** — Cyclomatic & Cognitive Complexity, LCOM4, TCC/LCC, RFC, Halstead, Maintainability Index - **Modern PHP** — built for PHP 8.4, leveraging php-parser v5 - **CI/CD ready** — text, JSON, Checkstyle, SARIF, and GitLab Code Quality output formats - **Baseline support** — ignore known issues, focus on new code quality - **Git integration** — analyze only changed or staged files ## Quick Example ```bash # Install composer require --dev qualimetrix/qualimetrix # Analyze your code vendor/bin/qmx check src/ # Use with git pre-commit hook vendor/bin/qmx hook:install # Report only violations from changed files vendor/bin/qmx check src/ --report=git:main..HEAD ``` ## Available Metrics | Category | Metrics | | ------------------- | ----------------------------------------------------------------- | | **Complexity** | Cyclomatic (CCN), Cognitive Complexity, NPATH Complexity | | **Maintainability** | Halstead metrics, Maintainability Index | | **Coupling** | CBO (RFC), Instability, Abstractness, Distance from Main Sequence | | **Cohesion** | TCC/LCC, LCOM4, WMC | | **Size** | LOC, Method Count, Class Count, Property Count | | **Structure** | DIT (Depth of Inheritance), NOC (Number of Children) | | **Architecture** | Circular Dependency Detection | | **Code Smells** | Boolean arguments, eval, goto, debug code, empty catch, and more | ## Getting Started Head to the [Quick Start](https://qualimetrix.github.io/qualimetrix/getting-started/quick-start/) guide to integrate Qualimetrix into your project in minutes. ## For AI Agents If you are an AI coding agent, see [llms.txt](https://qualimetrix.github.io/qualimetrix/llms.txt) for a concise machine-readable overview, or [llms-full.txt](https://qualimetrix.github.io/qualimetrix/llms-full.txt) for the complete reference in a single file. # Installation ## Requirements - **PHP 8.4** or higher - **Composer** (any modern version) > **Tip:** > Not sure which PHP version you have? Run `php -v` in your terminal. > ## Composer (recommended) Install Qualimetrix as a development dependency in your project: ```bash composer require --dev qualimetrix/qualimetrix ``` After installation, the `qmx` binary is available at: ```bash vendor/bin/qmx ``` ## PHAR > **Coming soon:** > A standalone PHAR archive is planned for future releases. This will allow you to run Qualimetrix without adding it to your project's dependencies. > ## Docker Run Qualimetrix in a container without installing PHP locally: ```bash docker run --rm -v $(pwd):/app qmx check src/ ``` This mounts your current directory into the container and analyzes the `src/` folder. You can pass any CLI options after `check`: ```bash # JSON output docker run --rm -v $(pwd):/app qmx check src/ --format=json # With baseline docker run --rm -v $(pwd):/app qmx check src/ --baseline=baseline.json ``` ## Verifying Installation **Composer:** ```bash vendor/bin/qmx --version ``` **Global or bin-dir:** ```bash bin/qmx --version ``` **Docker:** ```bash docker run --rm qmx --version ``` You should see output like: ``` Qualimetrix x.x.x ``` ## What's Next? Head to the [Quick Start](https://qualimetrix.github.io/qualimetrix/getting-started/quick-start/) guide to run your first analysis and set up integration with your workflow. # Quick Start Three ways to integrate Qualimetrix into your project: 1. **Pre-commit Hook** — check before every commit 2. **GitHub Action** — automatic checks in CI/CD 3. **Docker** — run without installing PHP locally ## Your First Analysis ### Install ```bash composer require --dev qualimetrix/qualimetrix ``` ### Run the analysis ```bash vendor/bin/qmx check src/ ``` ### Drill down into a namespace Investigate a specific namespace to see its classes and violations: ```bash vendor/bin/qmx check src/ --namespace='App\Service' ``` ### See detailed violations List individual violations with file paths, line numbers, and remediation hints: ```bash vendor/bin/qmx check src/ --detail ``` ### Generate an HTML report For a full interactive report with charts and drill-down navigation: ```bash vendor/bin/qmx check src/ --format=html -o report.html ``` Open `report.html` in your browser to explore the results. ## 1. Pre-commit Hook Automatic checking of staged files before every commit. ### Installation **Symbolic Link (recommended):** ```bash ln -s ../../scripts/pre-commit-hook.sh .git/hooks/pre-commit ``` Automatic updates when the script changes, no need to copy on updates. **Copy:** ```bash cp scripts/pre-commit-hook.sh .git/hooks/pre-commit chmod +x .git/hooks/pre-commit ``` Works if `.git/hooks` does not support symlinks, can be modified per project. **Built-in command:** ```bash vendor/bin/qmx hook:install ``` ### Usage After installation, the hook runs automatically on every `git commit`: ```bash git add src/MyClass.php git commit -m "Add new feature" # Hook will run automatically: # Running Qualimetrix on staged files... # Qualimetrix passed. ``` ### Bypassing the Hook ```bash # Skip the check for a specific commit git commit --no-verify -m "WIP: work in progress" ``` ### Setting Up Baseline If the project already contains legacy code with violations: ```bash # Create a baseline for existing issues vendor/bin/qmx check src/ --generate-baseline=baseline.json # Now the hook will ignore issues from the baseline git commit -m "Add feature" ``` ### Removing the Hook ```bash rm .git/hooks/pre-commit ``` ## 2. GitHub Action Automatic analysis on push and pull request. See the [GitHub Actions guide](https://qualimetrix.github.io/qualimetrix/ci-cd/github-actions/) for detailed configuration. ### Quick Setup ```yaml # .github/workflows/quality.yml name: Code Quality on: [push, pull_request] jobs: qmx: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Run Qualimetrix uses: qualimetrix/qualimetrix@v1 with: paths: 'src/' baseline: 'baseline.json' ``` # Analyze the current directory docker run --rm -v $(pwd):/app qmx check src/ # With baseline docker run --rm -v $(pwd):/app qmx check src/ --baseline=baseline.json # With configuration docker run --rm -v $(pwd):/app qmx check src/ --config=qmx.yaml # JSON output docker run --rm -v $(pwd):/app qmx check src/ --format=json ``` ### Docker Compose ```yaml # docker-compose.yml services: qmx: image: qmx:latest volumes: - .:/app:ro - ./baseline.json:/app/baseline.json command: check src/ --baseline=baseline.json ``` ```bash docker-compose run --rm qmx ``` ### CI/CD with Docker **GitLab CI:** ```yaml # .gitlab-ci.yml qmx: stage: test image: qmx:latest script: - qmx check src/ --baseline=baseline.json artifacts: when: on_failure paths: - qmx-results.json ``` **Jenkins:** ```groovy // Jenkinsfile pipeline { agent any stages { stage('Qualimetrix Analysis') { steps { script { docker.image('qmx:latest').inside('-v $WORKSPACE:/app') { sh 'qmx check src/ --baseline=baseline.json' } } } } } } ``` ## Excluding Paths Suppress violations for files matching glob patterns. Useful for generated code, DTOs, or entity classes. > **Note:** > Excluded files are still analyzed (metrics are collected) — only violations are suppressed. > **YAML Configuration:** ```yaml # qmx.yaml exclude_paths: - src/Entity/* - src/DTO/* ``` **CLI:** ```bash vendor/bin/qmx check src/ --exclude-path='src/Entity/*' --exclude-path='*/DTO/*' ``` CLI patterns are merged with those defined in the config file. # Check that the hook exists and is executable ls -la .git/hooks/pre-commit chmod +x .git/hooks/pre-commit ``` **`qmx binary not found`:** ```bash composer install ls -la bin/qmx ``` ### Docker Permission Issues ```bash # Linux with SELinux: add :z flag docker run --rm -v $(pwd):/app:z qmx check src/ ``` # Configuration Qualimetrix works out of the box with sensible defaults. A configuration file lets you customize thresholds, disable rules, and exclude paths to fit your project. ## Configuration File Create a file named `qmx.yaml` in your project root. Qualimetrix automatically looks for this file. You can also specify a file explicitly: ```bash vendor/bin/qmx check src/ --config=my-config.yaml ``` ## Configuration Sections ### Paths Directories to analyze: ```yaml paths: - src/ ``` > **Note:** > If you pass paths as CLI arguments (e.g., `vendor/bin/qmx check src/ lib/`), they take precedence over the config file. > ### Exclude Directories to skip entirely. Files in these directories are not analyzed at all: ```yaml exclude: - vendor/ - tests/Fixtures/ ``` ### Include Generated By default, files with a `@generated` annotation in the first 2 KB are automatically skipped from analysis. To include them: ```yaml include_generated: true ``` Equivalent CLI: `--include-generated` ### Exclude Paths Path patterns for suppressing violations. Unlike `exclude`, these files **are still analyzed** (their metrics are collected), but violations are not reported. Supports both directory prefixes and glob patterns: ```yaml exclude_paths: - src/Entity # prefix: matches all files under src/Entity/ - src/Metrics/*Visitor.php # glob: matches visitor files only ``` ### Exclude Namespaces Suppress violations for classes in specific namespaces (prefix matching). Like `exclude_paths`, files are still analyzed and metrics are collected, but violations are not reported. This applies to all rules globally: ```yaml exclude_namespaces: - App\Tests - App\Generated ``` This is useful when entire namespace subtrees should never produce violations. For per-rule exclusions, use `exclude_namespaces` inside a rule configuration instead (see below). Also available as a CLI option: `--exclude-namespace` (merged with YAML config). ### Rules Control which rules are active and set custom thresholds. **Disable a rule entirely:** ```yaml rules: code-smell.boolean-argument: enabled: false ``` **Override thresholds:** Each rule defines severity levels. When a metric exceeds a threshold, a violation is reported at that severity. For example, the cyclomatic complexity rule has thresholds for methods: ```yaml rules: complexity.cyclomatic: method: warning: 15 error: 25 ``` This means: report a **warning** when a method's cyclomatic complexity reaches 15, and an **error** when it reaches 25. **Threshold shorthand:** If you want a single pass/fail threshold (all violations become errors), use the `threshold` key: ```yaml rules: complexity.cyclomatic: method: threshold: 15 # warning=15, error=15 → all violations are errors size.method-count: threshold: 25 # same as warning: 25, error: 25 ``` This is useful in CI where you want a simple pass/fail cutoff without graduated warnings. You cannot mix `threshold` with explicit `warning`/`error` keys in the same rule level. For type coverage, dedicated shorthand keys are available: ```yaml rules: design.type-coverage: param_threshold: 90 return_threshold: 90 property_threshold: 80 ``` **Exclude namespaces from a rule:** Any rule can exclude specific namespaces using prefix matching. Violations from matching namespaces are suppressed: ```yaml rules: complexity.cyclomatic: exclude_namespaces: - App\Tests - App\Legacy method: warning: 15 error: 25 coupling.cbo: exclude_namespaces: - App\Tests exclude_paths: - src/Infrastructure/DependencyInjection ``` This is useful when certain namespaces (e.g., tests, generated code, legacy modules) should not trigger violations for a specific rule, while still being analyzed for metrics. **Exclude paths from a rule:** Any rule can exclude specific file paths using prefix or glob matching. Violations from matching files are suppressed: ```yaml rules: coupling.cbo: exclude_paths: - src/Metrics # prefix: all files in src/Metrics/ - src/Metrics/*Visitor.php # glob: only visitor files ``` This works alongside `exclude_namespaces` -- both filters are applied. Unlike the global `exclude_paths`, per-rule `exclude_paths` only affects the specific rule, not all rules. **Per-symbol threshold overrides with `@qmx-threshold`:** In addition to project-wide thresholds in YAML, you can override thresholds for individual classes or methods using `@qmx-threshold` annotations directly in source code: ```php /** * @qmx-threshold complexity.cyclomatic method.warning=20 method.error=40 */ class ComplexStateMachine { // Methods in this class use higher complexity thresholds } ``` See [Baseline > @qmx-threshold](https://qualimetrix.github.io/qualimetrix/usage/baseline.md#per-symbol-threshold-overrides-with-qmx-threshold) for full syntax and examples. ### Disabled Rules Disable specific rules or entire groups: ```yaml disabled_rules: - code-smell.boolean-argument - duplication ``` Equivalent CLI: `--disable-rule=code-smell.boolean-argument --disable-rule=duplication` ### Only Rules Run only specified rules (everything else is disabled): ```yaml only_rules: - complexity.cyclomatic - complexity.cognitive ``` Equivalent CLI: `--only-rule=complexity.cyclomatic --only-rule=complexity.cognitive` ### Fail On Control which severity levels cause a non-zero exit code: ```yaml fail_on: error # Only fail on errors (default) # fail_on: warning # Fail on warnings too # fail_on: none # Never fail on violations ``` The default is `error`: warnings are shown in the output but do not cause a non-zero exit code. Use `fail_on: warning` if you want warnings to also fail the build. ### Exclude Health Exclude specific health dimensions from scoring. The excluded dimensions are not shown in the health summary and do not contribute to the overall score: ```yaml exclude_health: - typing - maintainability ``` Equivalent CLI: `--exclude-health=typing --exclude-health=maintainability` ### Memory limit Set the PHP memory limit for analysis. By default, PHP's `memory_limit` from `php.ini` is used. ```yaml memory_limit: 1G # 1 gigabyte # memory_limit: -1 # Unlimited ``` Equivalent CLI: `--memory-limit=1G` ### Format Set the default output format: ```yaml format: summary # Default # format: json # format: html ``` ### Cache Control AST caching for faster repeated runs: ```yaml cache: enabled: true # Default: true dir: .qmx-cache # Default: .qmx-cache ``` Equivalent CLI: `--no-cache` to disable, `--cache-dir=DIR` to change directory. ### Parallel Processing Control the number of parallel workers for file analysis: ```yaml parallel: workers: 4 # Fixed number of workers # workers: 0 # Disable parallelism (single-threaded) ``` By default, Qualimetrix auto-detects the optimal worker count based on CPU cores. Equivalent CLI: `--workers=4` > **Tip:** > Use `workers: 0` for debugging or when running in environments without `ext-parallel`. > ### Namespace Detection Control how Qualimetrix resolves namespace-to-directory mapping: ```yaml namespace: strategy: chain # Default: chain (try psr4, then tokenizer) # strategy: psr4 # PSR-4 only (requires composer.json) # strategy: tokenizer # Parse namespace from PHP tokens composer_json: composer.json # Path to composer.json for PSR-4 detection ``` ### Coupling Configure framework namespace prefixes for the CBO (Coupling Between Objects) metric. Dependencies on framework namespaces are tracked separately as `cbo_app` and `ce_framework`: ```yaml coupling: framework-namespaces: - Symfony - Doctrine - Psr - Illuminate ``` When no `framework-namespaces` are configured, `cbo_app` equals `cbo` (no effect). ### Aggregation Control how namespaces are grouped for aggregated metrics: ```yaml aggregation: prefixes: - App\Domain - App\Infrastructure auto_depth: 2 # Auto-detect depth for namespace grouping ``` ## Presets | Preset | Description | | -------- | ----------------------------------------------------------------- | | `strict` | Tight thresholds for greenfield projects. Sets `fail_on: warning` | | `legacy` | Relaxed thresholds for legacy codebases. Disables noisy rules | | `ci` | Explicit CI mode. Sets `fail_on: error` | ```bash # Use a single preset vendor/bin/qmx check src/ --preset=strict # Combine multiple presets vendor/bin/qmx check src/ --preset=strict,ci # Use a custom preset file vendor/bin/qmx check src/ --preset=./my-preset.yaml ``` ## Full Example ```yaml # Or start with a preset and customize: # vendor/bin/qmx check src/ --preset=strict paths: - src/ exclude: - vendor/ - tests/Fixtures/ exclude_paths: - src/Entity - src/DTO exclude_namespaces: - App\Tests include_generated: false format: summary fail_on: error # default — warnings shown but don't fail the build cache: enabled: true dir: .qmx-cache parallel: workers: 4 coupling: framework-namespaces: - Symfony - Doctrine exclude_health: - typing disabled_rules: - code-smell.boolean-argument - duplication rules: complexity.cyclomatic: exclude_namespaces: - App\Tests exclude_paths: - src/Generated method: warning: 15 error: 25 size.method-count: warning: 25 error: 40 ``` ## CLI Options Override Config Command-line options always take precedence over values in the configuration file. For example: ```bash # Config says paths: [src/], but CLI overrides it vendor/bin/qmx check lib/ # Add extra exclude paths on top of config vendor/bin/qmx check src/ --exclude-path='src/Generated/*' ``` This makes it easy to experiment without editing the config file. ## Configuration Validation Qualimetrix validates your configuration file and reports clear errors for common mistakes. ### Unknown keys Any unrecognized key — at the root level or inside a section — produces an error with a suggestion: ``` Invalid configuration in qmx.yaml: Unknown key "workes" in "parallel" section. Did you mean "workers"? ``` ### Type errors If a value has the wrong type, you'll get a clear message instead of silent fallback to defaults: ``` Invalid value for "cache.enabled": expected boolean, got string ``` ### Unknown rule names Misspelled rule names in the `rules:` section are rejected: ``` Unknown rule "complexty.cyclomatic" in qmx.yaml. Did you mean "complexity.cyclomatic"? ``` > **Tip:** > Set a value to `~` (YAML null) or leave it empty to explicitly use the default — this is always valid. > ## What's Next? See the [CLI Options](https://qualimetrix.github.io/qualimetrix/usage/cli-options/) reference for the complete list of command-line options. # Usage Scenarios Qualimetrix fits into several development workflows. This page describes the most common scenarios and recommended configurations for each. ## CI/CD Pipeline The most common scenario. Qualimetrix runs on every push or pull request and blocks merges if quality standards are not met. **Recommended configuration:** - Use `only_rules` in your config file to pin the set of active rules. This prevents new rules from breaking your pipeline when you upgrade Qualimetrix. - The default `--fail-on=error` allows warnings without failing the build. Use `--fail-on=warning` if you want strict enforcement. - Use a [baseline](https://qualimetrix.github.io/qualimetrix/usage/baseline/) for legacy projects to focus on new violations only. - Use `--format=github` for inline annotations in GitHub PRs, or `--format=sarif` for the GitHub Security tab. **Example config (qmx.yaml):** ```yaml fail_on: error only_rules: - complexity - coupling.cbo - size rules: complexity.cyclomatic: method: warning: 10 error: 20 ``` **Example GitHub Actions workflow:** ```yaml - name: Run Qualimetrix run: vendor/bin/qmx check src/ --format=github --no-progress ``` Since `--fail-on=error` is the default, you don't need to specify it explicitly. ### Upgrading Qualimetrix in CI When upgrading Qualimetrix to a new version, new rules may be added. If you use `only_rules`, new rules won't activate automatically. If you don't use `only_rules`, review the CHANGELOG for new rules and either: - Add them to `disabled_rules` if you don't want them - Regenerate your baseline: `vendor/bin/qmx check src/ --generate-baseline=baseline.json` > **Tip:** > Combining `only_rules` with a baseline gives you the most stable CI experience. You control exactly which rules run and which existing violations are ignored. > ## Pre-commit Hook Fast feedback loop during local development. Qualimetrix checks only staged files before each commit. **Setup:** ```bash bin/qmx hook:install ``` **How it works:** - Analyzes only staged PHP files (fast) - Blocks the commit if error-severity violations are found - Respects your project's `qmx.yaml` and baseline **Tips:** - If a commit is blocked, you can fix the issues or skip the hook with `git commit --no-verify` - The hook automatically analyzes only staged files - The default `--fail-on=error` means warnings pass through; use `--fail-on=warning` for stricter enforcement > **Note:** > The hook analyzes only the staged version of each file. If you stage partial changes (`git add -p`), the hook checks exactly what will be committed. > ## AI-Assisted Development A developer (with or without an AI coding assistant) writes code, then runs Qualimetrix to check quality before submitting for review. **Workflow:** 1. Write or generate code 2. Run `bin/qmx check src/` to get a list of violations 3. Review the results and decide what to fix, ignore, or suppress 4. For issues worth fixing, either fix manually or delegate to your AI assistant with a specific instruction like "reduce cyclomatic complexity of method X by extracting helper methods" 5. Re-run Qualimetrix to verify fixes **Tips:** - Use `--format=json` if your AI tool works better with structured data - Use `--report=git:main..HEAD` to focus on violations in your changed files only - The text format is already optimized for terminal and IDE consumption -- no special "AI format" is needed ## Code Review Qualimetrix annotates pull requests with quality findings, giving reviewers objective data alongside the code diff. **GitHub -- inline annotations (recommended):** ```yaml - name: Run Qualimetrix run: vendor/bin/qmx check src/ --format=github --no-progress ``` Violations appear as warning/error annotations directly on the changed lines in the PR diff. No extra setup required. Only errors cause the build to fail (the default). **GitHub -- Security tab:** ```yaml - name: Run Qualimetrix run: vendor/bin/qmx check src/ --format=sarif --no-progress > results.sarif - name: Upload SARIF uses: github/codeql-action/upload-sarif@v3 with: sarif_file: results.sarif ``` **GitLab -- Code Quality widget:** ```yaml script: - vendor/bin/qmx check src/ --format=gitlab --no-progress > gl-code-quality-report.json artifacts: reports: codequality: gl-code-quality-report.json ``` **Scoped reporting:** To show violations only for changed files (not the entire project): ```bash vendor/bin/qmx check src/ --report=git:main..HEAD --format=github --no-progress ``` > **Tip:** > Scoped reporting with `--report=git:main..HEAD` is especially useful for large projects where a full report would overwhelm reviewers with pre-existing issues. > ## Comparison | Scenario | Recommended format | Key options | | ----------- | ------------------------------ | ------------------------------------------------------ | | CI/CD | `github` or `sarif` | `only_rules` in config, `--fail-on=warning` for strict | | Pre-commit | `text` (default) | Automatic via `hook:install` | | AI-assisted | `text` or `json` | `--report=git:main..HEAD` | | Code review | `github`, `sarif`, or `gitlab` | `--report=git:main..HEAD` | # CLI Options Qualimetrix provides the `check` command for code analysis and several utility commands for baseline management, git hooks, and dependency graph visualization. ## check command ```bash bin/qmx check [options] [--] [...] ``` ### Paths argument Specify one or more directories or files to analyze: ```bash # Analyze specific directories bin/qmx check src/ lib/ # Analyze a single file bin/qmx check src/Service/UserService.php ``` If you omit paths, Qualimetrix auto-detects them from the `autoload` section of your `composer.json`. ## File options ### `--config`, `-c` Path to a YAML configuration file: ```bash bin/qmx check src/ --config=qmx.yaml ``` ### `--exclude` Exclude directories from analysis. Can be repeated: ```bash bin/qmx check src/ --exclude=src/Generated --exclude=src/Legacy ``` ### `--include-generated` By default, Qualimetrix automatically skips files that contain a `@generated` annotation in the first 2 KB. This flag overrides that behavior and includes generated files in the analysis: ```bash bin/qmx check src/ --include-generated ``` Can also be set in `qmx.yaml`: ```yaml include_generated: true ``` ### `--exclude-path` Suppress violations for files matching a glob pattern. The files are still analyzed (their metrics contribute to namespace-level calculations), but violations are not reported. Can be repeated: ```bash bin/qmx check src/ --exclude-path="src/Entity/*" --exclude-path="src/DTO/*" ``` ### `--exclude-namespace` Suppress violations for classes in namespaces matching a prefix or glob pattern. The classes are still analyzed (their metrics contribute to aggregated calculations), but violations are not reported. Can be repeated: ```bash bin/qmx check src/ --exclude-namespace="App\Entity" --exclude-namespace="App\DTO\*" ``` Merged with `exclude_namespaces` from `qmx.yaml` — both sources are combined. ## Preset options ### `--preset` Apply a named preset or a custom YAML file. Can be repeated or comma-separated: ```bash # Built-in presets bin/qmx check src/ --preset=strict bin/qmx check src/ --preset=legacy # Combine presets (merged left-to-right) bin/qmx check src/ --preset=strict,ci bin/qmx check src/ --preset=strict --preset=ci # Custom preset file bin/qmx check src/ --preset=./my-preset.yaml ``` Available built-in presets: `strict`, `legacy`, `ci`. Presets are applied after `composer.json` auto-detection but before `qmx.yaml`, so your config file always takes precedence. See [Configuration > Presets](https://qualimetrix.github.io/qualimetrix/getting-started/configuration.md#presets) for details. ## Output options ### `--format`, `-f` Choose the output format. Default: `summary`. ```bash bin/qmx check src/ --format=json bin/qmx check src/ --format=sarif ``` Available formats: `summary`, `text`, `text-verbose`, `json`, `metrics`, `checkstyle`, `sarif`, `gitlab`, `github`, `health`. See [Output Formats](https://qualimetrix.github.io/qualimetrix/usage/output-formats/) for details on each format. ### `--group-by` Group violations in the output. Default depends on the formatter. ```bash bin/qmx check src/ --format=text-verbose --group-by=rule ``` Available values: `none`, `file`, `rule`, `severity`, `class`, `namespace`. ### `--format-opt` Pass formatter-specific options as key=value pairs. Can be repeated: ```bash bin/qmx check src/ --format-opt=key=value ``` **JSON format options:** | Option | Default | Description | | ------------------- | ------- | ------------------------------------ | | `violations=N\|all` | all | Max violations in output (0=none) | | `limit=N` | all | Alias for `violations` | | `top=N` | 10 | Number of worst offenders to include | ```bash bin/qmx check src/ --format=json --format-opt=limit=100 bin/qmx check src/ --format=json --format-opt=violations=all ``` ### `--fail-on` Set the minimum severity that causes a non-zero exit code. Default: `error`. ```bash # Default behavior: only errors cause non-zero exit code bin/qmx check src/ # Also fail on warnings bin/qmx check src/ --fail-on=warning # Never fail on violations bin/qmx check src/ --fail-on=none ``` By default, warnings are shown in the output but do not cause CI failure. Use `--fail-on=warning` to also fail on warnings. Can also be set in `qmx.yaml`: ```yaml fail_on: warning # also fail on warnings ``` ### `--exclude-health` Exclude specific health dimensions from scoring. The excluded dimensions are not shown in the health summary and do not contribute to the overall score. Can be repeated: ```bash # Exclude typing from health scoring bin/qmx check src/ --exclude-health=typing # Exclude multiple dimensions bin/qmx check src/ --exclude-health=typing --exclude-health=maintainability ``` Available dimensions: `complexity`, `cohesion`, `coupling`, `typing`, `maintainability`. Can also be set in `qmx.yaml`: ```yaml exclude_health: - typing ``` ### `--detail` Show a grouped violation list after the summary. Only affects `summary` format. ```bash # Default limit (200 violations) bin/qmx check src/ --detail # Show all violations (no limit) bin/qmx check src/ --detail=all # Custom limit bin/qmx check src/ --detail=50 ``` Auto-enabled when `--namespace` or `--class` is used. ### `--all` Show all violations without truncation. This is a shorthand for `--format-opt=violations=all --detail=all`. ```bash # Show all violations in JSON format bin/qmx check src/ --format=json --all # Show all violations in summary format bin/qmx check src/ --all ``` Cannot be combined with `--format-opt=violations=N` (numeric limit) — this produces a clear error. Combining `--all` with `--format-opt=violations=all` is allowed (they are synonyms). ### `--namespace` Filter output to a specific namespace subtree. Uses boundary-aware prefix matching. ```bash bin/qmx check src/ --namespace=App\\Service ``` Filters violations and worst offenders to the specified namespace. Shows subtree health scores. Auto-enables `--detail`. Mutually exclusive with `--class`. ### `--class` Filter output to a specific class by exact FQCN match. ```bash bin/qmx check src/ --class=App\\Service\\UserService ``` Filters violations to the specified class. Auto-enables `--detail`. Mutually exclusive with `--namespace`. ## Cache options Qualimetrix caches parsed ASTs to speed up repeated runs. ### `--no-cache` Disable caching entirely: ```bash bin/qmx check src/ --no-cache ``` ### `--cache-dir` Set a custom cache directory. Default: `.qmx-cache`. ```bash bin/qmx check src/ --cache-dir=/tmp/qmx-cache ``` ### `--clear-cache` Clear the cache before running analysis: ```bash bin/qmx check src/ --clear-cache ``` ## Baseline options Baselines let you ignore known violations and focus on new ones. See [Baseline](https://qualimetrix.github.io/qualimetrix/usage/baseline/) for the full guide. ### `--generate-baseline` Run analysis and save all current violations to a baseline file: ```bash bin/qmx check src/ --generate-baseline=baseline.json ``` ### `--baseline` Filter out violations that exist in the baseline file: ```bash bin/qmx check src/ --baseline=baseline.json ``` ### `--show-resolved` Show how many violations from the baseline have been fixed: ```bash bin/qmx check src/ --baseline=baseline.json --show-resolved ``` ### `--baseline-ignore-stale` By default, Qualimetrix reports an error if the baseline references files that no longer exist. This flag silently ignores stale entries instead: ```bash bin/qmx check src/ --baseline=baseline.json --baseline-ignore-stale ``` ## Suppression options ### `--show-suppressed` Show violations that were suppressed by `@qmx-ignore` tags: ```bash bin/qmx check src/ --show-suppressed ``` ### `--no-suppression` Ignore all `@qmx-ignore` tags and report every violation: ```bash bin/qmx check src/ --no-suppression ``` ## Git scope options Report only violations from changed files. See [Git Integration](https://qualimetrix.github.io/qualimetrix/usage/git-integration/) for the full guide. ### `--report` Control which violations to report. Analyzes the full project but only shows violations from changed files: ```bash bin/qmx check src/ --report=git:main..HEAD bin/qmx check src/ --report=git:origin/develop..HEAD ``` ### `--report-strict` In diff mode, only show violations from the changed files themselves. Without this flag, violations from parent namespaces are also shown: ```bash bin/qmx check src/ --report=git:main..HEAD --report-strict ``` ## Execution options ### `--workers`, `-w` Control parallel processing. Default: auto-detect based on CPU count. ```bash # Disable parallel processing (single-threaded) bin/qmx check src/ --workers=0 # Use exactly 4 workers bin/qmx check src/ --workers=4 ``` > **Tip:** > Use `--workers=0` for debugging or when running in environments that do not support `ext-parallel`. > ### `--memory-limit` Set the PHP memory limit for analysis. By default, PHP's `memory_limit` from `php.ini` is used. ```bash # Set memory limit to 1GB for large projects bin/qmx check src/ --memory-limit=1G # Unlimited memory bin/qmx check src/ --memory-limit=-1 ``` Valid formats: `-1` (unlimited), or a positive integer with optional `K`/`M`/`G` suffix (e.g., `512M`, `2G`). Equivalent YAML: `memory_limit: 1G` ### `--log-file` Write a debug log to a file: ```bash bin/qmx check src/ --log-file=qmx.log ``` ### `--log-level` Set the minimum log level. Default: `info`. ```bash bin/qmx check src/ --log-file=qmx.log --log-level=debug ``` Available levels: `debug`, `info`, `warning`, `error`. ### `--no-progress` Disable the progress bar. Useful in CI pipelines: ```bash bin/qmx check src/ --no-progress ``` # Show profiling summary on screen bin/qmx check src/ --profile # Save profile to file bin/qmx check src/ --profile=profile.json ``` ### `--profile-format` Choose the profile export format. Default: `json`. ```bash bin/qmx check src/ --profile=profile.json --profile-format=chrome-tracing ``` Available formats: `json`, `chrome-tracing`. > **Tip:** > Use `chrome-tracing` format and open the file in Chrome DevTools (chrome://tracing) for a visual timeline. > ## Rule options ### `--disable-rule` Disable a specific rule or an entire group by prefix. Can be repeated: ```bash # Disable one rule bin/qmx check src/ --disable-rule=size.class-count # Disable all complexity rules bin/qmx check src/ --disable-rule=complexity # Disable multiple bin/qmx check src/ --disable-rule=complexity --disable-rule=design.lcom ``` > **Memory optimization:** > Disabling `duplication.code-duplication` also skips the memory-intensive duplication detection phase entirely. On large codebases (500+ files), this can significantly reduce memory usage. Use `--disable-rule=duplication` if you encounter out-of-memory errors. > ### `--only-rule` Run only the specified rules or groups. Can be repeated: ```bash # Run only complexity rules bin/qmx check src/ --only-rule=complexity # Run two specific rules bin/qmx check src/ --only-rule=complexity.cyclomatic --only-rule=size.method-count ``` ### `--rule-opt` Override rule options from the command line. Format: `rule-name:option=value`. Can be repeated: ```bash bin/qmx check src/ --rule-opt=complexity.cyclomatic:method.warning=15 bin/qmx check src/ --rule-opt=complexity.cyclomatic:method.error=30 ``` ## Other commands ### baseline:cleanup Remove stale entries (references to files that no longer exist) from a baseline file: ```bash bin/qmx baseline:cleanup baseline.json ``` ### graph:export Export the dependency graph for visualization: ```bash # Export as DOT (default) bin/qmx graph:export src/ -o graph.dot # Export as JSON (aggregated adjacency list with metadata) bin/qmx graph:export src/ --format=json -o graph.json # Export as Mermaid bin/qmx graph:export src/ --format=mermaid -o graph.md # Filter by namespace bin/qmx graph:export src/ --namespace=App\\Service --namespace=App\\Repository # Exclude namespaces bin/qmx graph:export src/ --exclude-namespace=App\\Generated # Change layout direction bin/qmx graph:export src/ --direction=TB # Disable namespace grouping bin/qmx graph:export src/ --no-clusters ``` | Option | Description | | ------------------------ | ------------------------------------------------------- | | `-o`, `--output=FILE` | Output file (default: stdout) | | `-f`, `--format=FORMAT` | `dot` (default), `json`, or `mermaid` | | `-d`, `--direction=DIR` | Graph direction: `LR`, `TB`, `RL`, `BT` (default: `LR`) | | `--no-clusters` | Do not group nodes by namespace | | `--namespace=NS` | Include only these namespaces (repeatable) | | `--exclude-namespace=NS` | Exclude these namespaces (repeatable) | ### hook:install Install a git pre-commit hook: ```bash bin/qmx hook:install # Overwrite existing hook bin/qmx hook:install --force ``` ### hook:status Show the current status of the pre-commit hook: ```bash bin/qmx hook:status ``` ### hook:uninstall Remove the pre-commit hook: ```bash bin/qmx hook:uninstall # Restore the original hook from backup bin/qmx hook:uninstall --restore-backup ``` ### rules List all available rules with their descriptions and CLI options: ```bash # List all rules bin/qmx rules # Filter by group bin/qmx rules --group=complexity ``` **Example output:** ``` complexity.cyclomatic Cyclomatic complexity (McCabe) --cyclomatic-warning=N method.warning (default: 10) --cyclomatic-error=N method.error (default: 20) --cyclomatic-class-warning=N class.max_warning (default: 30) --cyclomatic-class-error=N class.max_error (default: 50) complexity.cognitive Cognitive complexity (SonarSource) --cognitive-warning=N method.warning (default: 15) --cognitive-error=N method.error (default: 30) ... ``` # Git Integration Qualimetrix integrates with Git to analyze only the code you have changed. This saves time and helps you catch issues before they reach the main branch. ## Why analyze only changed code? Running a full analysis on a large codebase can take time. More importantly, a legacy project may have hundreds of existing violations that are not your responsibility right now. Git integration solves both problems: - **Speed** -- analyze only the files you touched - **Focus** -- see only the violations you introduced - **Gradual adoption** -- start using Qualimetrix without fixing every old issue first ## Quick start The two most common scenarios: ```bash # Before committing: install a pre-commit hook bin/qmx hook:install # Before merging: check what changed vs main bin/qmx check src/ --report=git:main..HEAD ``` ## Pre-commit workflow Install a Git hook to automatically check staged files before each commit: ```bash bin/qmx hook:install ``` This creates a `.git/hooks/pre-commit` script that automatically runs Qualimetrix on staged files before each commit. Only PHP files that are currently staged are analyzed, making it fast. If violations with severity `error` are found, the commit is blocked. Check the hook status: ```bash bin/qmx hook:status ``` Remove the hook: ```bash bin/qmx hook:uninstall ``` If you already had a pre-commit hook, Qualimetrix backs it up. To restore it: ```bash bin/qmx hook:uninstall --restore-backup ``` > **Warning:** > `hook:install` will not overwrite an existing hook unless you pass `--force`. > ## PR workflow with --report The `--report` option shows only violations in files that changed compared to a Git reference: ```bash # Compare against main branch bin/qmx check src/ --report=git:main..HEAD # Compare against a specific branch bin/qmx check src/ --report=git:origin/develop..HEAD # Compare against a specific commit bin/qmx check src/ --report=git:abc1234..HEAD ``` > **Note:** > With `--report`, Qualimetrix still analyzes the full codebase (it needs complete metrics for namespace-level rules). It only *filters the output* to show violations from changed files. > ## How --report works The `--report` option controls which violations are shown in the output. Qualimetrix still analyzes the full codebase (it needs complete metrics for namespace-level rules), but only reports violations from the changed files: ```bash # Analyze everything, report only changed files bin/qmx check src/ --report=git:main..HEAD ``` This gives accurate metrics while only showing relevant violations. | Scenario | Recommendation | | ------------------------------- | ------------------------- | | Pre-commit hook (speed matters) | `bin/qmx hook:install` | | PR review (accuracy matters) | `--report=git:main..HEAD` | | CI pipeline with full analysis | `--report=git:main..HEAD` | ## --report-strict By default, when using `--diff` or `--report`, Qualimetrix also shows violations from parent namespaces of the changed files. This is useful because adding a class to a namespace can push it over size limits. If you want to see only violations from the changed files themselves: ```bash bin/qmx check src/ --report=git:main..HEAD --report-strict ``` ## Scope syntax The `--report` option accepts scope expressions: | Expression | Meaning | | -------------------------- | -------------------------------------------- | | `git:staged` | Files staged for commit | | `git:main..HEAD` | Files changed between main and HEAD | | `git:origin/develop..HEAD` | Files changed between remote branch and HEAD | | `git:abc1234..HEAD` | Files changed since a specific commit | ## Example workflows ### Local development ```bash # One-time setup bin/qmx hook:install # Now every commit is checked automatically git add src/Service/UserService.php git commit -m "refactor: simplify UserService" # Qualimetrix runs automatically on staged files, blocks commit if errors found ``` ### Pull request review ```bash # On your feature branch, check against main bin/qmx check src/ --report=git:main..HEAD # Strict mode: only violations in your changed files bin/qmx check src/ --report=git:main..HEAD --report-strict # With JSON output for CI bin/qmx check src/ --report=git:main..HEAD --format=json --no-progress ``` ### CI pipeline (GitHub Actions) ```yaml - name: Run Qualimetrix run: bin/qmx check src/ --report=git:origin/main..HEAD --format=sarif --no-progress > results.sarif - name: Upload SARIF uses: github/codeql-action/upload-sarif@v3 with: sarif_file: results.sarif ``` ### CI pipeline (GitLab CI) ```yaml code_quality: script: - bin/qmx check src/ --report=git:origin/main..HEAD --format=gitlab --no-progress > gl-code-quality-report.json artifacts: reports: codequality: gl-code-quality-report.json ``` # Baseline A baseline is a snapshot of all current violations in your project. Once you have a baseline, Qualimetrix only reports **new** violations -- anything that was already there is silently ignored. ## Why use a baseline? When you add Qualimetrix to an existing project, the first run may report hundreds of violations. You cannot fix them all at once. A baseline lets you: - **Start today** -- adopt Qualimetrix without fixing every legacy issue - **Prevent new debt** -- every new violation is reported immediately - **Track progress** -- see how many old violations you have fixed over time ## Creating a baseline Run analysis with the `--generate-baseline` flag: ```bash bin/qmx check src/ --generate-baseline=baseline.json ``` This runs the full analysis and saves all violations to `baseline.json`. The file is a JSON document with stable hashes for each violation, so it works even when line numbers shift. > **Tip:** > Commit `baseline.json` to your repository. This way, the whole team shares the same baseline. > ## Using a baseline Pass the `--baseline` flag on subsequent runs: ```bash bin/qmx check src/ --baseline=baseline.json ``` Qualimetrix loads the baseline, runs the analysis, and only reports violations that are **not** in the baseline. If you introduced a new violation, you will see it. If you fixed an old one, it silently disappears from the baseline matches. ## How it works Each violation in the baseline is identified by: - **File path** -- relative path to the source file - **Violation code** -- rule identifier (e.g., `complexity.cyclomatic.method`) - **Symbol path** -- the class, method, or namespace where the violation occurs - **Content hash** -- a stable hash of the file contents When Qualimetrix runs with a baseline, it matches current violations against baseline entries. If a match is found, the violation is filtered out. ## Tracking progress with --show-resolved Want to know how many old violations you have fixed? Use `--show-resolved`: ```bash bin/qmx check src/ --baseline=baseline.json --show-resolved ``` This adds a summary line showing the count of resolved violations -- entries that exist in the baseline but no longer appear in the current analysis. ## Stale entries A baseline entry becomes "stale" when the file it references no longer exists (e.g., a file was deleted or renamed). By default, Qualimetrix reports an error when stale entries are found. You have two options: ### Option 1: Ignore stale entries ```bash bin/qmx check src/ --baseline=baseline.json --baseline-ignore-stale ``` ### Option 2: Clean up the baseline Remove all stale entries permanently: ```bash bin/qmx baseline:cleanup baseline.json ``` > **Tip:** > Run `baseline:cleanup` periodically (e.g., after major refactoring) to keep your baseline file clean. > ## Inline suppression with @qmx-ignore For cases where a violation is intentional and you do not want it in the baseline, you can suppress it directly in the code using comments. Suppression tags work in all comment styles: - PHPDoc docblocks: `/** @qmx-ignore rule */` - Line comments: `// @qmx-ignore rule` - Block comments: `/* @qmx-ignore rule */` > **Limitation:** > Inline same-line comments are not supported: `$x = foo(); // @qmx-ignore rule` will **not** work. > Place the comment on a separate line before the target. > ### Suppress a specific rule ```php class LegacyProcessor { /** * @qmx-ignore complexity.cyclomatic This method handles all legacy formats */ public function process(array $data): array { // complex but intentional logic } } ``` ### Suppress all rules for a symbol ```php /** * @qmx-ignore * Generated code, do not analyze */ class GeneratedMapper { // ... } ``` ### Suppress all rules for an entire file Add a file-level docblock at the top of the file: ```php delete($key); } catch (CacheException) { // @qmx-ignore code-smell.empty-catch Best-effort caching } ``` ### Suppression tag syntax | Tag | Scope | Example | | --------------------------------------- | ---------------------------------- | ------------------------------------------------------- | | `@qmx-ignore [reason]` | The symbol this comment belongs to | `@qmx-ignore complexity.cyclomatic Legacy code` | | `@qmx-ignore * [reason]` | All rules for this symbol | `@qmx-ignore * Generated code` | | `@qmx-ignore-next-line [reason]` | The next line only | `@qmx-ignore-next-line code-smell.exit CLI entry point` | | `@qmx-ignore-file` | Entire file | `@qmx-ignore-file` | The rule name supports prefix matching: `@qmx-ignore complexity` suppresses all `complexity.*` rules. ### Viewing suppressed violations To see what was suppressed: ```bash bin/qmx check src/ --show-suppressed ``` ### Ignoring suppression tags To run analysis as if no `@qmx-ignore` tags existed: ```bash bin/qmx check src/ --no-suppression ``` ## Per-symbol threshold overrides with @qmx-threshold Sometimes a class or method legitimately needs different thresholds than the project default. Instead of suppressing the violation entirely with `@qmx-ignore`, you can override specific thresholds using `@qmx-threshold` annotations. ### Override a threshold for a class ```php /** * @qmx-threshold complexity.cyclomatic method.warning=20 method.error=40 */ class ComplexStateMachine { // Methods in this class use higher complexity thresholds } ``` ### Override a threshold for a method ```php class OrderProcessor { /** * @qmx-threshold complexity.cyclomatic warning=25 error=50 * @qmx-threshold complexity.npath warning=500 error=2000 */ public function processLegacyOrder(array $data): Order { // This method handles many legacy edge cases } } ``` ### Syntax ``` @qmx-threshold