github / gh-copilot

Ask for assistance right in your terminal.
https://docs.github.com/en/copilot/github-copilot-in-the-cli
689 stars 29 forks source link

[FEAT]: Inclusion of Helper Commands (??, git?, gh?) from Private Beta in New Copilot CLI Public Beta #5

Closed 0xdevalias closed 5 months ago

0xdevalias commented 10 months ago

Summary

During the GitHub Copilot CLI private beta, users had access to a set of concise helper commands that enhanced efficiency and streamlined workflows. These included ?? for arbitrary shell commands, git? for Git commands, and gh? for GitHub CLI commands. The new public beta of the Copilot CLI seems to be missing these helpful shortcuts.

Feature Request

I am writing to request the inclusion of these shorter helper commands in the new version of the GitHub Copilot CLI currently in public beta.

Background

In the private beta version of the GitHub Copilot CLI (accessible through @githubnext/github-copilot-cli on npm and detailed on GitHub Next), there was functionality that allowed users to quickly generate shell, Git, and GitHub CLI commands using the succinct ??, git?, and gh? commands, respectively. This feature significantly improved the developer experience by simplifying command invocation and saving time.

Current Version

In the current public beta version of the GitHub Copilot CLI (gh-copilot), this functionality is not present, or at least not clearly documented. The absence of these shortcuts requires users to revert to longer-form commands, which is less efficient.

Request

I would like to request that these commands, or similar ones, be included in the new version of the Copilot CLI. They were incredibly useful in the private beta and would be a valuable addition to the public beta.

Additional Context

The shorter helper commands were not only a convenience but also aligned well with the rapid command execution that developers appreciate. As someone who has been part of the private beta and experienced the efficiency these commands bring to the table, I believe their inclusion in the public beta will enhance user satisfaction and productivity.

0xdevalias commented 10 months ago

I guess looking a little closer, the underlying functionality is still there, just not the helper wrappers:

⇒ gh copilot suggest -h
Suggest a command based on a natural language description of the desired output effect.

There is no task too small or too large to need help when working in the terminal, the only limit is your imagination:

- installing and upgrading software
- troubleshooting and debugging problems with your system
- processing and manipulating files
- working with git and GitHub in the terminal

Usage:
  copilot suggest [flags]

Examples:

- Guided experience
  $ gh copilot suggest

- Git use cases
  $ gh copilot suggest -t git "Undo the most recent local commits"
  $ gh copilot suggest -t git "Clean up local branches"
  $ gh copilot suggest -t git "Setup LFS for images"

- Working with the GitHub CLI in the terminal
  $ gh copilot suggest -t gh "Create pull request"
  $ gh copilot suggest -t gh "List pull requests waiting for my review"
  $ gh copilot suggest -t gh "Summarize work I have done in issues and pull requests for promotion"

- General use cases
  $ gh copilot suggest -t shell "Kill processes holding onto deleted files"
  $ gh copilot suggest -t shell "Test whether there are SSL/TLS issues with github.com"
  $ gh copilot suggest -t shell "Convert SVG to PNG and resize"
  $ gh copilot suggest -t shell "Convert MOV to animated PNG"

Flags:
  -h, --help            help for suggest
  -t, --target target   Target for suggestion; must be shell, gh, git

We used to be able to set it up in our dotfiles/similar like this:

# github-copilot-cli (https://www.npmjs.com/package/@githubnext/github-copilot-cli)
if (( $+commands[github-copilot-cli] ))
then
  echo "Loading github-copilot-cli.."
  eval "$(github-copilot-cli alias -- "$0")"
fi

Where in zsh, the github-copilot-cli alias -- "$0" command would generate this:

⇒ github-copilot-cli alias -- "$0"

  copilot_what-the-shell () {
    TMPFILE=$(mktemp);
    trap 'rm -f $TMPFILE' EXIT;
    if /Users/devalias/.nodenv/versions/16.15.1/bin/github-copilot-cli what-the-shell "$@" --shellout $TMPFILE; then
      if [ -e "$TMPFILE" ]; then
        FIXED_CMD=$(cat $TMPFILE);
        print -s "$FIXED_CMD";
        eval "$FIXED_CMD"
      else
        echo "Apologies! Extracting command failed"
      fi
    else
      return 1
    fi
  };
alias '??'='copilot_what-the-shell';

  copilot_git-assist () {
    TMPFILE=$(mktemp);
    trap 'rm -f $TMPFILE' EXIT;
    if /Users/devalias/.nodenv/versions/16.15.1/bin/github-copilot-cli git-assist "$@" --shellout $TMPFILE; then
      if [ -e "$TMPFILE" ]; then
        FIXED_CMD=$(cat $TMPFILE);
        print -s "$FIXED_CMD";
        eval "$FIXED_CMD"
      else
        echo "Apologies! Extracting command failed"
      fi
    else
      return 1
    fi
  };
alias 'git?'='copilot_git-assist';

  copilot_gh-assist () {
    TMPFILE=$(mktemp);
    trap 'rm -f $TMPFILE' EXIT;
    if /Users/devalias/.nodenv/versions/16.15.1/bin/github-copilot-cli gh-assist "$@" --shellout $TMPFILE; then
      if [ -e "$TMPFILE" ]; then
        FIXED_CMD=$(cat $TMPFILE);
        print -s "$FIXED_CMD";
        eval "$FIXED_CMD"
      else
        echo "Apologies! Extracting command failed"
      fi
    else
      return 1
    fi
  };
alias 'gh?'='copilot_gh-assist';
alias 'wts'='copilot_what-the-shell';
0xdevalias commented 10 months ago

Feeding all of the above into ChatGPT gives the following code as a solution for implementing these shorthands on the new CLI for zsh:

It looks like you've found that the functionality from the private beta has been integrated into the new version of GitHub Copilot CLI, but the shorthand command aliases you were accustomed to aren't present by default. You want to recreate these aliases for the new CLI version.

Here's a shell script that you could add to your ~/.zshrc or similar shell configuration file to mimic the behavior of the old aliases with the new gh copilot suggest command:

# GitHub Copilot CLI shorthand commands for the new version
# Place this in your .zshrc or equivalent file

# Function to handle general shell command suggestions
copilot_shell_suggest() {
  local cmd_suggestion
  cmd_suggestion=$(gh copilot suggest -t shell "$@")
  if [ $? -eq 0 ]; then
    echo "Suggested command: $cmd_suggestion"
    eval "$cmd_suggestion"
  else
    echo "Could not generate suggestion."
  fi
}
alias '??'='copilot_shell_suggest'

# Function to handle Git command suggestions
copilot_git_suggest() {
  local cmd_suggestion
  cmd_suggestion=$(gh copilot suggest -t git "$@")
  if [ $? -eq 0 ]; then
    echo "Suggested command: $cmd_suggestion"
    eval "$cmd_suggestion"
  else
    echo "Could not generate suggestion."
  fi
}
alias 'git?'='copilot_git_suggest'

# Function to handle GitHub CLI command suggestions
copilot_gh_suggest() {
  local cmd_suggestion
  cmd_suggestion=$(gh copilot suggest -t gh "$@")
  if [ $? -eq 0 ]; then
    echo "Suggested command: $cmd_suggestion"
    eval "$cmd_suggestion"
  else
    echo "Could not generate suggestion."
  fi
}
alias 'gh?'='copilot_gh_suggest'

# You can reload your shell configuration or start a new shell session to activate these commands.

I didn't really try that as is.. but I went with a simplified version for my own use:

# Check if the gh copilot extension is installed and load aliases accordingly
if gh extension list | grep -q 'github/gh-copilot'; then
  copilot_shell_suggest() {
    gh copilot suggest -t shell "$@"
  }
  alias '??'='copilot_shell_suggest'

  # Function to handle Git command suggestions
  copilot_git_suggest() {
    gh copilot suggest -t git "$@"
  }
  alias 'git?'='copilot_git_suggest'

  # Function to handle GitHub CLI command suggestions
  copilot_gh_suggest() {
    gh copilot suggest -t gh "$@"
  }
  alias 'gh?'='copilot_gh_suggest'
fi

You could also then potentially use concepts for adding the copied command to your command line (but not executing it) as explored in:

imanmahjoubi commented 10 months ago

@0xdevalias Thank you for your support in being an early adopter of this feature. Your feedback is highly valued, and I'll be sure to bring it up with the team to explore potential options.

andyfeller commented 10 months ago

@0xdevalias : Agreed, thank you for the feedback and being an early adopter! 🙇 I think you've touched on the bulk of what is missing to add this support with a small caveat.

What is missing?

The GitHub Next technical preview didn't execute commands directly: it uses a trick around the invocation using temporary file where it printed the command to execute.

    if /Users/devalias/.nodenv/versions/16.15.1/bin/github-copilot-cli git-assist "$@" --shellout $TMPFILE; then
      if [ -e "$TMPFILE" ]; then
        FIXED_CMD=$(cat $TMPFILE);
        print -s "$FIXED_CMD";
        eval "$FIXED_CMD"
      else
        echo "Apologies! Extracting command failed"
      fi
    else
      return 1
    fi

In the suggest / revise loop, the GitHub Next technical preview would write the command to the temporary file and exit:

  useInput(async (input, key) => {
    if (status !== "idle") return;

    if (key.escape) {
      setState("response");
    } else if (input === "y" || input === "Y") {
      await mutateAsync();
      if (shellOut) fs.writeFileSync(shellOut, lastResult);
      exit();
    } else if (input === "n" || input === "N") {
      trackConfirmCommandCancel();
      setState("response");
    }
  });

This definitely resonates with #2 suggestion as the 2 work together.

andyfeller commented 10 months ago

As an aside, the GitHub CLI gh alias command is an alternative for aliasing any GitHub CLI command including extensions:

$ gh alias list
co: pr checkout
explain: copilot explain
suggest-gh: copilot suggest -t gh
suggest-git: copilot suggest -t git
suggest-shell: copilot suggest -t shell

This shortens the invocation to something like gh suggest-shell.

For more information, check out the gh alias subcommands.

0xdevalias commented 10 months ago

In the suggest / revise loop, the GitHub Next technical preview

@andyfeller I notice that that link goes to a seemingly non-public repo (githubnext/copilot-cli). A little off topic, and probably a little irrelevant since the project is superseded now anyway (and if we really cared we could extract it from the previously published/packaged versions); but any chance of getting that repo made public?

paulschmeida commented 10 months ago

I was wondering about that as well and ended up implementing 3 functions to get this to work in Powershell:

function ?? {
    param([string]$query)
    gh copilot suggest -t shell "$query"
}
function gh? {
    param([string]$query)
    gh copilot suggest -t gh "$query"
}
function git? {
    param([string]$query)
    gh copilot suggest -t git "$query"
}

I've also implemented that in .bashrc on Ubuntu:

# Aliases for Github Copilot CLI
function ?? () {
    gh copilot suggest -t shell "$1"
}
function gh? () {
    gh copilot suggest -t gh "$1"
}
function git? () {
    gh copilot suggest -t git "$1"
}

You need to make sure there's a space after the function name, because it wouldn't work with ? in the name otherwise. After saving .bashrc, run source .bashrc to reload.

andyfeller commented 10 months ago

Thank you, @paulschmeida, for the contribution! ❤

As an aside, I've been iterating on some internal spikes figuring out what the aliasing, command execution, and history capabilities would look like in PowerShell in order to have confidence in supporting this, which you can see below.

That said, there were some concerns raised early on in the effort about the use of ? within aliases, given that ? is meaningful to many terminals, so I want to dig into concerns around that before making a commitment exactly. 🙇

Initial prototype of PowerShell aliasing, command execution, and history capabilities

```PowerShell function Copilot-CLI-Gh { param( [Parameter(Position=0)] [string[]]$Prompt ) Invoke-Copilot-CLI -Target gh $Prompt } # TODO: Rename function to desired short name function Copilot-CLI-Git { param( [Parameter(Position=0)] [string[]]$Prompt ) Invoke-Copilot-CLI -Target git $Prompt } # TODO: Rename function to desired short name function Copilot-CLI-Shell { Invoke-Copilot-CLI -Target shell $args } function Invoke-Copilot-CLI { param( [Parameter(Mandatory=$true)] [ValidateSet('gh', 'git', 'shell')] [String]$Target, [Parameter(Position=0)] [string[]]$Prompt ) begin { # Create temporary file to store potential command user wants to execute when exiting $executeCommandFile = New-TemporaryFile # TODO: Remove this test, injecting an arbitrary command for testing purposes into temp file Write-Output "Write-Output `"123`"" | Out-File -FilePath $executeCommandFile } process { # Invoke-Expression "gh copilot suggest -t $Target `"$Prompt`"" gh copilot suggest -t $Target $Prompt } end { # Execute command contained within temporary file if it is not empty if ($executeCommandFile.Length -gt 0) { # Extract command to execute from temporary file $executeCommand = (Get-Content -Path $executeCommandFile -Raw).Trim() # Insert command into PowerShell up/down arrow key history [Microsoft.PowerShell.PSConsoleReadLine]::AddToHistory($executeCommand) # Insert command into PowerShell history $now = Get-Date $executeCommandHistoryItem = [PSCustomObject]@{ CommandLine = $executeCommand ExecutionStatus = [Management.Automation.Runspaces.PipelineState]::NotStarted StartExecutionTime = $now EndExecutionTime = $now.AddSeconds(1) } Add-History -InputObject $executeCommandHistoryItem # Execute command # TODO: Maybe we're a little more explicit about what the command we're going to execute is Invoke-Expression $executeCommand } } clean { # Clean up temporary file used to store potential command user wants to execute when exiting Remove-Item -Path $executeCommandFile } } ```

perpil commented 10 months ago

Since it isn't entirely clear, are you looking into replicating this functionality and adding switches/wrapper script to support a similar interface to the command?

The GitHub Next technical preview didn't execute commands directly: it uses a trick around the invocation using temporary file where it printed the command to execute.

andyfeller commented 9 months ago

Since it isn't entirely clear, are you looking into replicating this functionality and adding switches/wrapper script to support a similar interface to the command?

The GitHub Next technical preview didn't execute commands directly: it uses a trick around the invocation using temporary file where it printed the command to execute.

@perpil : Yes. We've heard feedback from the technical preview users around how it handled executing commands for users within context of their existing shell environment as described here.

Mathuv commented 9 months ago

Thank you @paulschmeida

For zsh:

# Define functions
function gh_copilot_shell_suggest {
    gh copilot suggest -t shell "$1"
}
function gh_copilot_gh_suggest {
    gh copilot suggest -t gh "$1"
}
function gh_copilot_git_suggest {
    gh copilot suggest -t git "$1"
}

# Set aliases
alias '??'=gh_copilot_shell_suggest
alias 'gh?'=gh_copilot_gh_suggest
alias 'git?'=gh_copilot_git_suggest
RicardoM17 commented 9 months ago

Thank you @Mathuv that is definitely helpful.

As feedback for the maintainers it would be helpful if the demo in github next at least had some sort of note explaining that the ?? gh? and git? commands aren't available by default anymore.

@ perpil : Yes. We've heard feedback from the technical preview users around how it handled executing commands for users within context of their existing shell environment as described here.

I also agree that having an easier option to run the commands is very much needed but I see that is being discussed in another PR in that repo. However I wanted to ask if this link that you shared is supposed to be private?

I have a question I want to ask regarding the copilot commit messages and PR descriptions + CLI that would perhaps would be better suited in that repo as I don't want to hijack this one.

Thanks!

gabynevada commented 9 months ago

@Mathuv

Made a small modification so that you don't have to place your prompt in between ""

# Define functions
function gh_copilot_shell_suggest {
    gh copilot suggest -t shell "$*"
}
function gh_copilot_gh_suggest {
    gh copilot suggest -t gh "$*"
}
function gh_copilot_git_suggest {
    gh copilot suggest -t git "$*"
}

# Set aliases
alias '??'=gh_copilot_shell_suggest
alias 'gh?'=gh_copilot_gh_suggest
alias 'git?'=gh_copilot_git_suggest
0xdevalias commented 9 months ago

Made a small modification so that you don't have to place your prompt in between ""

@gabynevada That doesn't actually work for cases like this:

⇒ ?? does this actually work?
zsh: no matches found: work?

You could also have used the version I posted way back in November:

# Check if the gh copilot extension is installed and load aliases accordingly
if gh extension list | grep -q 'github/gh-copilot'; then
  copilot_shell_suggest() {
    gh copilot suggest -t shell "$@"
  }
  alias '??'='copilot_shell_suggest'

  # Function to handle Git command suggestions
  copilot_git_suggest() {
    gh copilot suggest -t git "$@"
  }
  alias 'git?'='copilot_git_suggest'

  # Function to handle GitHub CLI command suggestions
  copilot_gh_suggest() {
    gh copilot suggest -t gh "$@"
  }
  alias 'gh?'='copilot_gh_suggest'
fi

You could also then potentially use concepts for adding the copied command to your command line (but not executing it) as explored in:

Originally posted by @0xdevalias in https://github.com/github/gh-copilot/issues/5#issuecomment-1803088331

andyfeller commented 5 months ago

@0xdevalias : As you might have seen on #2, v1.0.0 with GitHub Copilot in the CLI GA has just release with support for executing commands and alias helpers like the technical preview!

Debuting with support for Bash, PowerShell, and Zsh, I hope we can work with others in the community to develop support for other popular shells. :heart:

For more information, see https://github.blog/changelog/2024-03-21-github-copilot-general-availability-in-the-cli/.

0xdevalias commented 5 months ago

@andyfeller Thanks for the update here, and for implementing the missing features based on our feedback :) I saw it this morning and am excited to check it out!