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 before the first run.
Overview
The code analyzer integrates Salesforce Code Analyzer into the project:analyze command and:
- Detects the configuration file (or uses engine defaults)
- Runs the configured engines (PMD, ESLint, CPD) against the target files
- Collects results in SARIF format
- Reports findings with file locations, line numbers, and rule details
- 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:
--code-analyzer-config <path>CLI flagcode-analyzer.yml(repository root)code-analyzer.yaml(repository root)config/code-analyzer.ymlconfig/code-analyzer.yaml.code-analyzer.yml.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
# 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: apexExamples
PMD-Only with Custom Rules
# config/code-analyzer.yml
engines:
pmd:
disable_rules:
- ApexUnitTestClassShouldHaveRunAs
custom_rulesets:
- config/pmd/salesforce-best-practices.xmlTighter Duplicate Detection
# config/code-analyzer.yml
engines:
cpd:
minimum_tokens: 75Disable PMD Rules That Don't Apply
# config/code-analyzer.yml
engines:
pmd:
disable_rules:
- ApexUnitTestClassShouldHaveRunAs
- AvoidDebugStatements
- ApexUnitTestClassShouldHaveAssertsFailing 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:
# only Critical (severity 1) violations fail the check; the rest are reported
sfp project:analyze --fail-on code-analyzer --code-analyzer-severity-threshold 1The 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):
# 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:RecommendedRepeat 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:
<ruleset name="Customer PMD Rules"> ... </ruleset>the selector is the tag CustomerPMDRules:
# 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:RecommendedUse 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
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.
# Run code analyzer and fail on issues
sfp project:analyze --fail-on code-analyzer --output-format github# 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:
# 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/defaultFor full engine configuration options, see the Salesforce Code Analyzer documentation.
AI Assisted Version Intent
An opt-in analyze addon that reads a pull request diff and applies a semantic version intent by posting a /version comment authored by the app.
Code Analyzer prerequisites
The PMD and CPD engines require a Java runtime and the Code Analyzer engine libraries. This page covers what to download and where to put it.