VS Code Salesforce Extensions
This skill activates when you need to set up a Salesforce development environment in Visual Studio Code, troubleshoot the Apex Language Server, configure deploy-on-save for source-tracked or non-tracked orgs, choose between Apex Interactive and Replay Debugger, or resolve workspace structure issues. It covers the Salesforce Extension Pack and its constituent extensions but not the underlying CLI commands themselves.
Before Starting
Gather this context before working on anything in this domain:
- JDK version: The Apex Language Server requires Java. JDK 21 is recommended; JDK 17 and 11 are also supported. The
salesforcedx-vscode-apex.java.homesetting must point to a valid JDK installation if the systemJAVA_HOMEis not set or points to a JRE. - Workspace root: The extension pack only activates fully when
sfdx-project.jsonis in the top-level folder opened in VS Code. Opening a parent directory or a subfolder breaks Apex Language Server activation. - Org authorization: At least one org must be authorized via
sf org login web(or the legacysfdx auth:web:login) before deploy, retrieve, or debug commands will work. The default org is set per-project, not globally.
Core Concepts
Apex Language Server
The Apex Language Server provides code completion, go-to-definition, inline errors, and rename support for .cls, .trigger, and anonymous Apex. It runs as a separate Java process managed by the salesforcedx-vscode-apex extension. It will not start if:
- No valid JDK is found (JRE alone is not sufficient).
sfdx-project.jsonis missing from the workspace root.- The workspace was opened at the wrong directory level.
When the language server starts, it indexes all Apex classes and triggers under the project's packageDirectories. Large orgs with thousands of classes may see a startup delay of 30-60 seconds. The status bar shows "Indexing" during this phase.
Deploy on Save
The salesforcedx-vscode-core extension offers a "Push or Deploy on Save" feature controlled by the salesforcedx-vscode-core.push-or-deploy-on-save.enabled setting. The behavior differs by org type:
- Source-tracked orgs (scratch orgs, source-tracked sandboxes): triggers
sf project deploy startwhich uses the source-tracking framework to deploy only changed files. - Non-source-tracked orgs (production, Developer Edition, non-tracked sandboxes): triggers
sf project deploy start --source-diron the individual saved file, deploying it immediately regardless of other pending changes.
This distinction is critical because deploying to a non-tracked org will overwrite whatever is on the server with no conflict detection.
Apex Debugging
Two debugger options exist, each serving different scenarios:
- Apex Interactive Debugger requires the "Apex Interactive Debugger" license (included with Performance and Unlimited editions, available as an add-on for others). It sets breakpoints in a live running org and halts execution server-side. A single debug session locks the org — no other debug sessions or Apex executions can proceed.
- Apex Replay Debugger requires no special license. It works by replaying a captured debug log locally, simulating variable state and execution flow. It does not halt live execution and is safe for shared orgs.
Common Patterns
Pattern: Fresh Workspace Setup
When to use: Starting a new Salesforce DX project or onboarding a developer to an existing repo.
How it works:
- Install the "Salesforce Extension Pack" from the VS Code marketplace (extension ID:
salesforce.salesforcedx-vscode). - Ensure JDK 21 is installed and
JAVA_HOMEis set, or configuresalesforcedx-vscode-apex.java.homein.vscode/settings.json. - Open the folder containing
sfdx-project.jsonas the workspace root. - Run
SFDX: Authorize an Orgfrom the Command Palette (orsf org login web --set-default). - Wait for the Apex Language Server to finish indexing (status bar shows "Indexing complete").
Why not the alternative: Opening a parent folder that contains the SFDX project as a subfolder will prevent the Apex Language Server from finding sfdx-project.json at root, causing silent feature degradation with no error message.
Pattern: Replay Debugger for Shared Development Orgs
When to use: Debugging Apex logic in a sandbox or scratch org shared by multiple developers, or when the org lacks the Interactive Debugger license.
How it works:
- Set
DEVELOPER_LOGtrace flags on the running user via Setup > Debug Logs, or usesf apex log get. - Execute the Apex scenario that needs debugging (trigger a page load, run a test, etc.).
- Retrieve the debug log: Command Palette >
SFDX: Get Apex Debug Logs. - Open the log file, then Command Palette >
SFDX: Launch Apex Replay Debugger with Current File. - Set breakpoints in the source
.clsfiles. The replay debugger will stop at those lines and show variable state from the log.
Why not the alternative: The Interactive Debugger locks the entire org for the duration of the session. In a shared org, this blocks all other Apex execution (triggers, flows calling Apex, scheduled jobs) until the session ends or times out.
Decision Guidance
| Situation | Recommended Approach | Reason |
|---|---|---|
| Solo developer on a scratch org | Interactive Debugger | No contention; real-time breakpoints are faster than replaying logs |
| Shared sandbox, no debugger license | Replay Debugger | No license needed; does not lock the org |
| Deploy-on-save for scratch org | Enable push-or-deploy-on-save | Source tracking handles conflict detection automatically |
| Deploy-on-save for production or DE org | Leave disabled; deploy manually | No conflict detection — auto-deploy can silently overwrite server changes |
| Apex LSP not starting | Check JDK path and workspace root | The two most common root causes by a wide margin |
| Large project with slow indexing | Reduce packageDirectories scope | The LSP indexes everything in declared packageDirectories |
Recommended Workflow
Step-by-step instructions for an AI agent or practitioner setting up or troubleshooting VS Code for Salesforce development:
- Verify prerequisites — Confirm JDK 21 (or 17/11) is installed (
java -version), not just a JRE. Confirm the Salesforce Extension Pack is installed and up to date. Check that Salesforce CLI (sf) is available onPATH. - Open the correct workspace root — The folder opened in VS Code must contain
sfdx-project.jsonat its top level. If working in a monorepo, use VS Code multi-root workspaces or open the SFDX project subfolder directly. - Authorize the target org — Run
SFDX: Authorize an Orgfrom the Command Palette. For CI or headless environments, usesf org login jwtinstead. Set the org as default withSFDX: Set a Default Org. - Configure deploy-on-save appropriately — For source-tracked orgs (scratch orgs, tracked sandboxes), enable
salesforcedx-vscode-core.push-or-deploy-on-save.enabled. For non-tracked orgs, leave it disabled and deploy manually to avoid silent overwrites. - Validate Apex Language Server — Open any
.clsfile and verify code completion and error highlighting work. If the status bar shows an error, checksalesforcedx-vscode-apex.java.homein settings and confirm the workspace root. - Set up debugging — If the org has the Interactive Debugger license, create a launch configuration of type
Launch Apex Debugger. Otherwise, configure trace flags and use the Replay Debugger workflow. - Commit workspace settings — Add
.vscode/settings.jsonand.vscode/launch.jsonto version control so team members inherit the same configuration.
Review Checklist
Run through these before marking work in this area complete:
- JDK 21 (or 17/11) is installed and the path is configured correctly in VS Code settings or
JAVA_HOME -
sfdx-project.jsonis at the root of the opened workspace folder - At least one org is authorized and set as the default org for the project
- Deploy-on-save is enabled only for source-tracked orgs; disabled for non-tracked orgs
- Apex Language Server shows "Indexing complete" in the status bar and code completion works
- Debug configuration matches the org type and license availability (Interactive vs Replay)
-
.vscode/settings.jsonand.vscode/launch.jsonare committed to the repo
Salesforce-Specific Gotchas
Non-obvious platform behaviors that cause real production problems:
- JRE vs JDK — Installing a Java Runtime Environment (JRE) instead of a full JDK is the most common reason the Apex Language Server fails to start. The extension requires
javacand related tooling, not justjava. - Workspace root mismatch — Opening the Git repo root when
sfdx-project.jsonlives one level down produces no error message. The extensions load but the Apex Language Server silently refuses to activate, leaving developers with no code completion and no explanation. - Deploy-on-save on non-tracked orgs overwrites without warning — Unlike source-tracked orgs where
sf project deploy startdetects conflicts, deploying a single file to a non-tracked org replaces whatever is on the server. If another developer changed the same file via Setup or another tool, their changes are lost. - Interactive Debugger locks the entire org — A single Interactive Debugger session blocks all other Apex execution in the org (triggers, batch jobs, flows calling Apex). Forgetting to disconnect the debugger can cause production-like failures in shared sandboxes.
- Multiple packageDirectories slow indexing — When
sfdx-project.jsondeclares manypackageDirectories, the Apex Language Server indexes all of them. In large monorepos this can take several minutes and consume significant memory.
Output Artifacts
| Artifact | Description |
|---|---|
.vscode/settings.json |
Workspace settings including JDK path, deploy-on-save toggle, and default org preferences |
.vscode/launch.json |
Debug launch configurations for Interactive or Replay Debugger |
sfdx-project.json |
Project descriptor that the extension pack requires at the workspace root |
Related Skills
sf-cli-and-sfdx-essentials— For CLI command reference, project creation, and org management commands outside the VS Code GUIscratch-org-management— For designing scratch org definition files and managing Dev Hub allocationssource-tracking-and-conflict-resolution— For understanding how source tracking works under deploy-on-savesalesforce-code-analyzer— For running static analysis from within VS Code via the Code Analyzer extension