---
schema_version: "1"
id: afbab44f5c89e082eb934be23ef81a0ad7d38bfc2eaa33f3a1a48ab6557be3ed
title: Integrate Your Plugin With the doctor Command
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/salesforcedx/sfcliplugin/guides/integrate-doctor.md
canonical_url: https://developer.salesforce.com/docs/platform/salesforce-cli-plugin/guide/integrate-doctor.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: f3d6c7e2525714d17394bcb22474b4d36b52847b30618d2976af1b23f0c20018
products:
  - Salesforce CLI Plugin Developer Guide
  - salesforcedx
---
# Integrate Your Plugin With the `doctor` Command

Salesforce CLI includes the `doctor` command that you can run if you're having issues with the CLI. The command inspects your CLI installation and environment, runs diagnostic tests, provides suggestions, and writes the data to a local diagnostic file. See the [Salesforce CLI Command Reference](https://developer.salesforce.com/docs/platform/salesforce-cli-reference/guide/cli_reference_doctor.html) and [Setup Guide](https://developer.salesforce.com/docs/atlas.en-us.sfdx_setup.meta/sfdx_setup/sfdx_setup_trouble_doctor.htm) for more information about the `doctor` command.

To help your users troubleshoot problems with your plugin, you can integrate it into the `doctor` command so it runs your custom diagnostic tests. You can add custom information to both the **Running all diagnostics** and **Suggestions** sections and to the JSON results file. For example:

```bash
$ sf doctor
=== Running all diagnostics

pass - salesforcedx plugin isn’t installed
pass - you don't have any linked plugins
warn - [@salesforce/plugin-deploy-retrieve] sourceApiVersion matches apiVersion
pass - [@salesforce/plugin-trust] can ping: https://registry.npmjs.org
pass - [@salesforce/plugin-trust] can ping: https://registry.yarnpkg.com
pass - [@salesforce/plugin-trust] can ping: https://registry.npmjs.org/
pass - using latest or latest-rc CLI version
pass - can access: https://test.salesforce.com
pass - can access: https://appexchange.salesforce.com/services/data
pass - can access: https://developer.salesforce.com/media/salesforce-cli/sf/channels/stable/sf-win32-x64-buildmanifest
fail - [@salesforce/plugin-auth] CLI supports v2 crypto

Wrote doctor diagnosis to: /Users/juliet.shackell/sfdx/dev-repos/cli.wiki/1721077460991-diagnosis.json

=== Suggestions

  * Check https://github.com/forcedotcom/cli/issues for CLI issues posted by the community.
  * Check http://status.salesforce.com for general Salesforce availability and performance.
  * Neither sourceApiVersion nor apiVersion are defined. The commands that deploy and retrieve source use the max apiVersion of the target org in this case. The issue isn't a problem, as long as it's the behavior you actually want.
  * using npm registry https://registry.npmjs.org/ from npm config
  * Your current installation of Salesforce CLI, including all the plugins you've linked and installed, doesn't yet support v2 crypto. All plugins and libraries must use at least version 6.7.0 of `@salesforce/core` to support v2 crypto. You're generally still able to successfully authenticate with your current CLI installation, but not if you generate a v2 crypto key.
```

## Why Write Plugin-Specific Diagnostic Tests

The main reason is to provide your users a quick and potential fix to an issue, and thus provide a better experience. Because you have a deep understanding of your plugin, you can likely predict potential problems your customers will run into. With the diagnostic tests, you can inspect their CLI and plugin configuration and suggest immediate actions if your users run into these predicted issues. If the suggestions don't fix the problem, the `doctor` gathers the required information that users attach to [GitHub issues](https://github.com/forcedotcom/cli/issues) or provide to Salesforce Customer Support.

Writing diagnostic tests isn't a replacement for good command error handling. Rather, it's a way to educate and clarify command usage within a complex system.

Examples of diagnostic tests include checking for:

- An environment variable that changes the behavior of your plugin or a library that your plugin uses.
- A setting within a project that changes plugin behavior.
- Required dependencies (outside of NPM) that are missing or out of date.
- A system that is required by your plugin that is unavailable.
- Anything that your customers regularly need clarification on that the commands can't handle directly.

## How to Integrate Your Plugin Into the Doctor

See the [diagnostic test in the deploy and retrieve plugin](https://github.com/salesforcecli/plugin-deploy-retrieve/blob/main/src/hooks/diagnostics.ts) for a real-life example. Also see the [source code for the `doctor` command](https://github.com/salesforcecli/plugin-info/blob/main/src/doctor.ts).

1. Define a hook in the `oclif` section of your plugin's `package.json` with this pattern, where `<plugin-name>` is the `name` property in your `package.json` file:

   ```json
   "sf-doctor-<plugin-name>": "./path/to/compiled/hook/handler"
   ```

   For example, the [`plugin-deploy-retrieve`](https://github.com/salesforcecli/plugin-deploy-retrieve/blob/main/package.json) diagnostic hook is defined with this JSON snippet. The Typescript source file and directory for the hook handler is `src/hooks/diagnostics.ts`:

   ```json
   "oclif": {
   ...
     "hooks": {
       "sf-doctor-@salesforce/plugin-deploy-retrieve": "./lib/hooks/diagnostics"
     }
   }
   ```

2. If you coded your plugin in TypeScript, add a `devDependencies` entry in `package.json` that points to `@salesforce/plugin-info`, which contains the required `SfDoctor` type. Use the latest version of [`plugin-info`](https://github.com/salesforcecli/plugin-info/releases). For example:

   ```json
   "devDependencies": {
     "@salesforce/plugin-info": "^3.3.18"
   }
   ```

3. In the hook handler source file (`src/hooks/diagnostics.ts` in our example), define and export a `hook` function that runs after the `doctor` command is executed. Here's a basic Typescript example that includes one diagnostic test called `test1`:

   ```typescript
   // Import the SfDoctor interface from plugin-info and Lifecycle class from  @salesforce/core
   import { SfDoctor } from "@salesforce/plugin-info";
   import { Lifecycle } from "@salesforce/core";

   // Define the shape of the hook function
   type HookFunction = (options: { doctor: SfDoctor }) => Promise<[void]>;

   // export the function
   export const hook: HookFunction = async (options) => {
     return Promise.all([test1(options.doctor)]);
   };

   const test1 = async (doctor: SfDoctor): Promise<void> => {
     // Add your code for "test1" here
   };
   ```

4. Code the `hook` function to return the result of all your plugin's diagnostic tests using `Promise.all([test1(), test2(), test3()]);`.
5. Use `doctor.addPluginData()` in your diagnostic tests to add JSON data to the full `doctor` diagnostics report. This JSON data appears in the `pluginSpecificData` section of the JSON report. For example, this code in the hook handler:

   ```typescript
   const pluginName = 'my-plugin';
   const prop1 = 'firstValue';
   const prop2 = 'secondValue';

   ...

     doctor.addPluginData(pluginName, {
       prop1,
       prop2,
     });
   ```

   Results in this JSON snippet in the full `doctor` diagnostic report:

   ```json
     "pluginSpecificData": {
       "my-plugin": [
         {
           "prop1": "firstValue",
           "prop2": "secondValue"
        }
       ]
     },
   ```

6. Use the global singleton `Lifecycle` class in your diagnostic tests to include the test name and status to the beginning section of the `doctor` command output. For example:

   ```typescript
   Lifecycle.getInstance().emit("Doctor:diagnostic", { testName, status });
   ```

   You must name the event `Doctor:diagnostic` and the payload must have this shape: `{ testName: string, status: string }`, where `status` is one of `'pass' | 'fail' | 'warn' | 'unknown'`

7. Use the `doctor.addSuggestion()` method in your diagnostic tests to add suggestions, based on the test results, to the last part of the `doctor` output. For example:

   ```typescript
   doctor.addSuggestion(
     "The environment variable ENV_VARIABLE is set, which can affect the behavior of the XX commands. Are you sure you want to set this env variable?",
   );
   ```

8. Diagnostic tests can reference the command run by the `doctor` and all generated command output from the `doctor` diagnostics. For example:

   ```typescript
     // Get the command string run by the doctor.
     const commandName = doctor.getDiagnosis().commandName;
     if (commandName?.includes('project:deploy:start') {
       /* run a test specific to that command */
     }

     // Parse the debug.log generated by the doctor.
     // The code must wait for the command to execute and logs to be written.
     const debugLog = doctor.getDiagnosis().logFilePaths;
     if (debugLog?.length) {
    // Get the log file path, read it, look for specific output, add suggestions.
     }
   ```
