> For the complete documentation index, see [llms.txt](https://docs.flxbl.io/flxbl/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flxbl.io/flxbl/sfp/analysing-a-project/code-analyzer.md).

# Code Analyzer

The code analyzer linter runs Salesforce Code Analyzer against your project, providing static analysis through PMD, ESLint, and CPD engines. It identifies security issues, best practice violations, performance concerns, and duplicate code.

The PMD and CPD engines run on the JVM and require a Java runtime and the Code Analyzer engine libraries on the machine running `sfp analyze`. See [Code Analyzer prerequisites](/flxbl/sfp/analysing-a-project/code-analyzer-prerequisites.md) before the first run.

### Overview

The code analyzer integrates Salesforce Code Analyzer into the `project:analyze` command and:

1. Detects the configuration file (or uses engine defaults)
2. Runs the configured engines (PMD, ESLint, CPD) against the target files
3. Collects results in SARIF format
4. Reports findings with file locations, line numbers, and rule details
5. Creates GitHub Checks with annotations when running in CI

When an engine cannot process a single file — a parse error on one class, for example — the run reports it as a scan warning and continues, so the remaining files' findings are still returned rather than the whole analysis failing. The warnings appear in the run's notes and in the `scanWarnings` field of the JSON output.

### Supported Engines

| Engine   | Language              | What It Checks                                |
| -------- | --------------------- | --------------------------------------------- |
| `pmd`    | Apex                  | Security, best practices, performance, design |
| `eslint` | LWC JavaScript / Aura | JavaScript quality, security, best practices  |
| `cpd`    | Apex, JavaScript      | Copy-paste / duplicate code detection         |

### Configuration

The code analyzer is configured through a YAML file that follows the Salesforce Code Analyzer v5 configuration format. The file is checked in priority order until the first match is found:

1. `--code-analyzer-config <path>` CLI flag
2. `code-analyzer.yml` (repository root)
3. `code-analyzer.yaml` (repository root)
4. `config/code-analyzer.yml`
5. `config/code-analyzer.yaml`
6. `.code-analyzer.yml`
7. `.code-analyzer.yaml`

The repository-root filenames match where the `sf code-analyzer` CLI looks by default, so a project already carrying a root `code-analyzer.yml` is picked up without moving it under `config/`.

If `--code-analyzer-config` names a path that does not exist, the command fails rather than falling back to the default rules. If no flag is given and none of the locations above exist, the default engine configuration is used (all engines with their built-in rule sets).

Paths inside the config — such as `custom_rulesets` — resolve relative to the repository root.

#### Schema

```yaml
# config/code-analyzer.yml

engines:
  pmd:
    # Disable specific PMD rules by name
    disable_rules:
      - ApexUnitTestClassShouldHaveAsserts
      - AvoidDebugStatements

    # Custom PMD rule sets (paths relative to repo root or URLs)
    custom_rulesets:
      - config/pmd/custom-rules.xml

    # Java heap size for PMD (MB)
    java_max_heap: 1024

  eslint:
    # Path to ESLint config file
    config_file: config/.eslintrc.json

    # Additional plugins to load
    plugins:
      - '@salesforce/eslint-plugin-lwc'

  cpd:
    # Minimum number of duplicate tokens to report
    minimum_tokens: 100

    # File extensions to scan for duplicates
    language: apex
```

### Examples

#### PMD-Only with Custom Rules

```yaml
# config/code-analyzer.yml
engines:
  pmd:
    disable_rules:
      - ApexUnitTestClassShouldHaveRunAs
    custom_rulesets:
      - config/pmd/salesforce-best-practices.xml
```

#### Tighter Duplicate Detection

```yaml
# config/code-analyzer.yml
engines:
  cpd:
    minimum_tokens: 75
```

#### Disable PMD Rules That Don't Apply

```yaml
# config/code-analyzer.yml
engines:
  pmd:
    disable_rules:
      - ApexUnitTestClassShouldHaveRunAs
      - AvoidDebugStatements
      - ApexUnitTestClassShouldHaveAsserts
```

### Failing on severity

By default any violation fails the check when `code-analyzer` is listed in `--fail-on`. `--code-analyzer-severity-threshold` restricts that to violations at or above a given severity, mirroring `sf code-analyzer run --severity-threshold`:

| Value | Severity       |
| ----- | -------------- |
| `1`   | Critical       |
| `2`   | High           |
| `3`   | Moderate       |
| `4`   | Low            |
| `5`   | Info (default) |

The default of `5` means every violation fails, so no existing project changes behaviour. Lower it to keep low-severity findings from blocking a build while still reporting them:

```bash
# only Critical (severity 1) violations fail the check; the rest are reported
sfp project:analyze --fail-on code-analyzer --code-analyzer-severity-threshold 1
```

The threshold is also settable per project in the server-side analyze configuration, where it applies to PR validation.

### Choosing which rules run

`--code-analyzer-rule-selector` chooses which rules run, mirroring `sf code-analyzer run --rule-selector`. The default is the engine name, which runs every rule of that engine. Scope a selector to an engine (`pmd:Security`, not bare `Security`):

```bash
# run one category
sfp project:analyze --code-analyzer-rule-selector pmd:Security

# a severity-bounded expression
sfp project:analyze --code-analyzer-rule-selector "pmd:(Security,Performance):2"

# Salesforce's Recommended set
sfp project:analyze --code-analyzer-rule-selector pmd:Recommended
```

Repeat the flag for several selectors. Commas and parentheses are part of the selector expression, so a selector is never split apart, and each selector must match at least one rule — a selector matching nothing is an error rather than a silent pass.

#### Running only your custom ruleset

`custom_rulesets` is additive: listing a ruleset makes its rules available, but it does not restrict the run, so the built-in rules still apply and a project configured only with `custom_rulesets` still reports rules outside its ruleset. To run only your ruleset, select it by name. Code Analyzer tags every rule loaded from a custom ruleset with the ruleset's `name` attribute, with spaces removed, so for:

```xml
<ruleset name="Customer PMD Rules"> ... </ruleset>
```

the selector is the tag `CustomerPMDRules`:

```bash
# only the rules in your ruleset
sfp project:analyze --code-analyzer-rule-selector pmd:CustomerPMDRules

# your ruleset plus Salesforce's Recommended set
sfp project:analyze \
  --code-analyzer-rule-selector pmd:CustomerPMDRules \
  --code-analyzer-rule-selector pmd:Recommended
```

Use the ruleset-name tag, not `pmd:Custom` — the `Custom` tag is added only to genuinely custom rules, so it would drop the standard PMD rules your ruleset references.

### Integration with CI/CD

{% hint style="info" %}
Integration is limited only to GitHub at the moment. The command needs GITHUB\_APP\_PRIVATE\_KEY and GITHUB\_APP\_ID to be set in environment variables for results to be reported as GitHub checks.
{% endhint %}

```bash
# Run code analyzer and fail on issues
sfp project:analyze --fail-on code-analyzer --output-format github
```

```yaml
# GitHub Actions
- name: Run Code Analysis
  run: |
    sfp project:analyze --fail-on code-analyzer --output-format github
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

### Scoping Analysis

Use the same scoping options as other analysis commands:

```bash
# By package
sfp project:analyze --fail-on code-analyzer -p core,utils

# By domain
sfp project:analyze --fail-on code-analyzer -d sales

# By source path
sfp project:analyze --fail-on code-analyzer -s ./force-app/main/default
```

> For full engine configuration options, see the [Salesforce Code Analyzer documentation](https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/config.html).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.flxbl.io/flxbl/sfp/analysing-a-project/code-analyzer.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
