When developing a custom CLI plugin, we're able to retrieve Org Connection using this.org.getConnection(), as the class is extending SfdxCommand.

How can I do the same thing in a CLI hook ?

I would like to query the org currently used in the command on which the Hook is running.


This is not full code and a pseudo-code at this point but should get you started. This also assumes its a pre-deploy hook for now.

Approach 1 - Establish another session using sfdx-core lib

You can use the sfdx-core library to use the keys stored in your local machine to easily establish a session.

The key here is to note that argv contains all the flags passed to the command, so you can read the username alias.

If no username alias found then read from the default project config in your workspace in which the command is run from.

import { Command, Hook } from '@oclif/config';
import * as sfcore from '@salesforce/core';

type HookFunction = (this: Hook.Context, options: HookOptions) => any;

type HookOptions = {
 Command: Command.Class;
 argv: string[];
 commandId: string;
 result?: PreDeployResult;

type PreDeployResult = {
 [aggregateName: string]: {
  mdapiFilePath: string;
  workspaceElements: {
     fullName: string;
      metadataName: string;
      sourcePath: string;
      state: string;
      deleteSupported: boolean;

 export const hook: HookFunction = async function(options) {
  console.log('PreDepoy Hook Running');
  let defaultusernamealias = ;

  //First check using the hooks arguments for the org alias

  //One way this can be done is by looking at the options.argv array to see if there is an username

 //write logic to parse the .sfdx/json file to get a default org in case no username was passed by the user

  let defaultusername = await sfcore.Aliases.fetch(defaultusernamealias);

  const connection = await sfcore.Connection.create({
    authInfo: await sfcore.AuthInfo.create({ username:  defaultusername})

 export default hook;

Alternative Approach - Uses sfdx-command lib and running commands programmatically

I am leaning more towards this but have not got a chance to try it out

You can create a typescript class that extends sfdx command in your plugin

import {SfdxCommand } from '@salesforce/command';

export default class Context extends SfdxCommand {

   public async run(): Promise<AnyJson> { 
    const conn = this.org.getConnection();
    // Do your logic here
    let response;
    return response;


Now in your hook file

// In your hook file

import {Context} from './context';

export const hook: HookFunction = async function(options) {
  console.log('PreDepoy Hook Running');

    await Context.run(['--app', flags.app]);

// Note you can design flags for it that can pass down to the command run as arguments.

This is calling the commands programmatically as documented here

  • Thanks, I just tried, but argv only contains what was passed explicitly to the command, so if I run sfdx force:source:pull, I'm not getting the username – Fabien Taillon Oct 12 '20 at 18:25
  • 1
    If no username is passed, you can try to read the default username from the project config file. – Abhishek Saxena Oct 12 '20 at 18:37
  • @FabienTaillon What Abhishek is saying. Its mentioned in the answer. You can get it from your config JSON or in fact, core lib has an aggregator class to get you that value. – Mohith Shrivastava Oct 12 '20 at 19:50
  • Sorry, I read to fast, missed that line ! Well I thought it would be easier to get this, as one of the great thing with regular (non hooks) CLI plugins is to get the full context. Actually reading the json file didn't worked directly because it's an alias, and Connection.create requires the username. It should work if I call sfdx force:org:display and use the result. More painful than I though but it should work, thanks ! – Fabien Taillon Oct 12 '20 at 20:03
  • @FabienTaillon Actually you need not go server-side unnecessarily for that info. You can use let defaultusername = await sfcore.Aliases.fetch(defaultusernamealias); I updated in the answer as well. – Mohith Shrivastava Oct 12 '20 at 20:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.