---
schema_version: "1"
id: 8b69ca1dc1ee48c976dbcee23b1dee6040f7c6acda4f2e2b9795a618c03b54fa
title: Add More Commands to Your Plugin
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/salesforcedx/sfcliplugin/guides/get-started/gs-add-commands.md
canonical_url: https://developer.salesforce.com/docs/platform/salesforce-cli-plugin/guide/gs-add-commands.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 8fe4463f312c2e83934a309b9272b5ec1413b95966a21cf390ae105f33f8efd2
products:
  - Salesforce CLI Plugin Developer Guide
  - salesforcedx
---
# Add More Commands to Your Plugin

Saying hello to the world is always fun, but you're likely ready to do more. Let's add two more commands to your plugin.

## Call an External Service

This section shows how to create a new command called `call external service`. The command makes an HTTP request to an [external service](http://numbersapi.com/random/trivia?json) that returns an interesting fact about a number. The command has no flags other than the ones you get for "free" (`--help`, `-h` and `--json`). When you enter the service's URL in your browser, it displays JSON with the interesting fact and some metadata about it.

1. Install [Got](https://www.npmjs.com/package/got), our recommended npm HTTP library, into your plugin by running this command:

   ```bash
   yarn add got
   ```

   Because the new command makes HTTP requests, you need an HTTP library. While you can use any library you want, we recommend Got because it’s simple yet full featured.

2. In a terminal, change to the top-level directory of your plugin and run this command to generate the initial files, or scaffolding:

   ```bash
   sf dev generate command --name call:external:service
   ```

   The command prompts if you want to overwrite the existing `package.json` file, enter `y` to update the file with information about the new command.

   The `--name` flag specifies the full colon-separated name of the command you want to create. For example, if you want to create the command `do awesome stuff`, set `--name` to `do:awesome:stuff`.

   The command generates these files, similar to the [files associated with the `hello world` command](https://developer.salesforce.com/docs/platform/salesforce-cli-plugin/guide/gs-generate-plugin.md#tour-the-generated-files):

   - `src/commands/call/external/service.ts`
   - `messages/call.external.service.md`
   - `test/command/call/external/service.nut.ts`
   - `test/command/call/external/service.test.ts`

   The Typescript files contain `import` statements for the minimum required Salesforce libraries, and scaffold some basic code. The new type names come from the value you passed to the `--name` flag.

3. Open up `src/commands/call/external/service.ts` in your IDE, such as Visual Studio Code.

4. Add this `import` statement to the beginning of the file with the other `import` statements:

   ```typescript
   import got from 'got';
   ```

5. Let’s now handle the JSON returned by our new command when a user runs it with the `--json` flag, which all CLI commands have by default. We want our command to return the JSON provided by the external service’s API. The underlying CLI framework uses the return type of the command class’ `run` method, which in this case is `CallExternalServiceResult`. So replace the code for `CallExternalServiceResult` to reflect the service’s JSON:

   ```typescript
   export type CallExternalServiceResult = {
     text: string;
     number: number;
     found: boolean;
     type: string;
   };
   ```

6. Let’s next work with the command flags. Remember that our command doesn't have any flags beyond the default ones, so remove this code inside the `CallExternalService` class which declares a flag that we no longer need:

   ```typescript
       public static readonly flags = {
         name: Flags.string({
           summary: messages.getMessage('flags.name.summary'),
           description: messages.getMessage('flags.name.description'),
           char: 'n',
           required: false,
         }),
       }
   ```

   Then remove the `Flags` import from `@salesforce/sf-plugins-core` at the beginning of the file. After removing `Flags` from the import statement, the import looks like this:

   ```typescript
   import { SfCommand } from '@salesforce/sf-plugins-core';
   ```

7. The final coding step is to update the `run` method inside the `CallExternalService` class. This method is where you put the logic for your command. In our case, we want our command to make an HTTP GET request to the service API and return the result. Replace the `run` method with this code:

   ```typescript
   public async run(): Promise<CallExternalServiceResult> {
       const result = await got<CallExternalServiceResult>(
         'http://numbersapi.com/random/trivia?json'
       ).json<CallExternalServiceResult>();

       this.log(result.text);

       return result;
   }
   ```

   In the preceding code, `this.log` logs the interesting fact to the terminal only if the `–json` flag is _not_ provided. In other words, the underlying CLI framework is smart enough to know whether to log non-JSON output, like strings, to the terminal.

8. We're ready to test! Open a Terminal, either in VS Code or outside, and run the command using `bin/dev.js`.

   ```bash
   bin/dev.js call external service
   ```

   Hopefully you see an interesting fact like this:

   `54 is the number of countries in Africa.`

   Let’s try the freebie flags, the ones that are magically available even though you didn't explicitly add them. First get help for the command:

   ```bash
   bin/dev.js call external service --help
   ```

   The help message isn't that useful yet because you haven't updated the boilerplate content in `messages/call.external.service.md`. We show an example of updating the help in the next example. Now run the command again but get JSON output instead of the default human-readable:

   ```bash
   bin/dev.js call external service --json
   ```

Good job adding a new command! Now let’s create something more Salesforce-y.

## Connect to a Salesforce Org

Next create a more complex command that connects to a Salesforce org and displays a list of all Account names and IDs.

The command has one new flag, `--target-org`, with short name `-o`. Use the flag to specify the username or alias of an org you’ve previously logged into, also known as _authorized_, with the `login org` command. Do you recognize the flag? It's a standard flag that many of the core Salesforce CLI commands use, such as `project deploy start`. You can use the flag too, including its existing code to connect to an org. Let's give it a try.

1. In a terminal, change to the top-level directory of your plugin and run this command to generate the initial command files; answer `y` to overwrite the `package.json` file:

   ```bash
   sf dev generate command --name connect:org
   ```

   Here's the list of generated files:

   - `src/commands/connect/org.ts`
   - `messages/connect.org.md`
   - `test/command/connect/org.nut.ts`
   - `test/command/connect/org.test.ts`

2. Run this interactive command to generate a flag. In this context, "generate" means update the existing command files with the required information for the new `--target-org` flag:

   ```bash
   sf dev generate flag
   ```

   Be sure you specify these properties of the new flag when prompted:

   - Command to add a new flag: `connect org`
   - Type: `requiredOrg`
   - Use standard definition: Y
   - Flag name: `--target-org` (default)

   The command updates two files: `src/commands/connect/org.ts` with the new flag code and `messages/connect.org.md` with a new entry for the flag's summary, which is displayed when you run the command with the `--help` flag.

3. Open `src/commands/connect/org.ts` in your IDE and review the new generated code for the `--target-org` flag:

   ```typescript
       'target-org': Flags.requiredOrg(),
   ```

   Because we're using _existing_ code for the flag, the single line of code is all you need -- magic!

4. Because `org.ts` still contains code for the `--name` flag, which was added automatically when you originally generated the command, remove it now, just to keep things tidy. This is the code you can remove from `public static readonly flags`:

   ```typescript
   name: Flags.string({
     summary: messages.getMessage('flags.name.summary'),
     description: messages.getMessage('flags.name.description'),
     char: 'n',
     required: false,
   }),
   ```

   The new flag is ready! Let's now code the command functionality.

5. Update the command’s return type (`ConnectOrgResult`) with this code:

   ```typescript
   export type ConnectOrgResult = Array<{ Name: string; Id: string }>;
   ```

6. Update the `run` method with this code:

   ```typescript
   public async run(): Promise<ConnectOrgResult> {
     // parse the provided flags
     const { flags } = await this.parse(ConnectOrg);

     // Get the orgId from the Org instance stored in the `target-org` flag
     const orgId = flags['target-org'].getOrgId();
     // Get the connection from the Org instance stored in the `target-org` flag
     const connection = flags['target-org'].getConnection();

     this.log(`Connected to ${flags['target-org'].getUsername()} (${orgId}) with API version ${connection.version}`);

     // Use the connection to execute a SOQL query against the org
     const result = await connection.query<{ Name: string; Id: string }>('SELECT Id, Name FROM Account');

     // Log the results
     if (result.records.length > 0) {
       this.log('Found the following Accounts:');
       for (const record of result.records) {
         this.log(`  • ${record.Name}: ${record.Id}`);
       }
     } else {
       this.log('No Accounts found.');
     }

     return result.records;
   }
   ```

   Your new command is now ready to test!

7. If you haven't already done so, log in to your test org with the `org login web` command. Run `org list` to see the orgs you've previously logged into and their associated usernames and aliases. We'll use the username or alias to test your new command.

   Logging into an org before you work with it is standard Salesforce CLI practice. Think about `project deploy start`: it too takes a username (also via the `--target-org` flag) of the org you want to deploy to, and it's assumed that you've previously logged into it.

8. Test your new command with `bin/dev.js`; replace `<org-username-or-alias>` with the username or alias of the org you just logged into:

   ```bash
   bin/dev.js connect org --target-org <org-username-or-alias>
   ```

   Hopefully you see output similar to this (the record IDs have been truncated for security):

   ```bash
   Connected to <your-org-username> (<your-org-id>) with API version 64.0
   Found the following Accounts:`
     • Acme: 001B...`
     • salesforce.com: 001B...`
     • Global Media: 001B...
     • TestAccount: 001B...
     • xyz: 001B...
     • Test1: 001B...
   ```

   Make sure that the short flag name works too!

   ```bash
   bin/dev.js connect org -o <your-org-username>
   ```

Pretty cool, huh.
