Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

GitHub Copilot for CLI 소개

이제 GitHub Copilot은 쓰진 않더라도 대부분 존재는 알고 있을 정도로 보급이 된 편인데 GitHub Copilot for CLI는 CLI에서 AI에 돕는 프로젝트로 간단히 말하면 자연어를 입력하면 CLI 명령어를 만들어 준다.

GitHub Next에서는 다양한 실험 프로젝트를 진행하고 있는데 얼마 전에 공개된 GitHub Copilot X는 AI로 소프트웨어 개발을 돕는 여러 Copilot 제품군의 집합이라고 생각할 수 있고 GitHub Copilot for CLI도 GitHub Copilot X에 포함되어 있다.

GitHub Copilot for CLI 설치

GitHub Copilot for CLI는 현재 waitlist에 등록하고 승인받아야 사용할 수 있고 얼마전에 승인을 받아서 사용해 볼 수 있게 되었다.

GitHub Copilot for CLI는 소스 코드가 공개되어 있지는 않은데 npm에 배포되어 있으므로 npm으로 설치해서 사용할 수 있다.

$ npm install -g @githubnext/github-copilot-cli
npm WARN deprecated @opentelemetry/api-metrics@0.33.0: Please use @opentelemetry/api >= 1.3.0

added 233 packages, and audited 234 packages in 12s

47 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

나는 Node.js 개발을 하기 때문에 쉽게 설치했지만 Node.js 환경이 필요하기 때문에 접근성이 좋다고 할 수는 없다. 아직 실험단계로 npm을 유지하고 있는지 이후로도 npm 배포를 유지할 예정인지는 잘 모르겠다.

어쨌든 설치했으니 명령어를 github-copilot-cli 명령어를 사용할 수 있다.

$ github-copilot-cli
Usage: Copilot CLI [options] [command]

A CLI experience for letting GitHub Copilot help you on the command line.

Options:
  -V, --version                        output the version number
  -h, --help                           display help for command

Commands:
  auth                                 Retrieve and store a GitHub Access Token.
  alias <shell path>                   Add convenient GitHub Copilot CLI aliases to your shell.
  what-the-shell [options] <query...>  Use GitHub Copilot to get shell commands from natural language
                                       descriptions.
  git-assist [options] <query...>      Translate a natural language description of a git command to an actual git
                                       command.
  gh-assist [options] <query...>       Convert plain english to GitHub CLI commands.
  help [command]                       display help for command

$ github-copilot-cli --version
0.1.30

npm에 배포되어 있으므로 설치는 누구나 할 수 있지만 실제 사용은 GitHub 계정을 인증해야 한다. github-copilot-cli auth 명령어로 인증을 하면 GitHub 페이지에서 인증해서 사용할 수 있다.

$ github-copilot-cli auth
Copy this code: CDE3-724F

Then go to https://github.com/login/device, paste the code in and approve the access.


GitHub Copilot for CLI 설정

앞의 명령어 목록을 보면 3개의 명령어가 있음을 알 수 있다.

  • github-copilot-cli what-the-shell: 자연어를 쉘 명령어로 변환한다.
  • github-copilot-cli git-assist: 자연어를 git 명령어로 변환한다.
  • github-copilot-cli gh-assist: 자연어를 GitHub CLI 명령어로 변환한다.(이전 글 참고)

GitHub Copilot for CLI에서 제공하는 기능도 이 3가지인데 쉘, Git, gh 3가지를 다르게 명령어를 사용해야 한다. 하지만 이 긴 명령어를 쓴다면 실제로 사용할 때 전혀 편하지 않을 것이다. 그래서 github-copilot-cli에서 별칭 기능을 제공한다.

아래 명령어를 쉘의 프로파일에 추가하면 되는데 나는 ZSH을 사용하고 있으므로 $HOME/.zshrc 파일에 아래 명령어를 추가했다.

eval "$(github-copilot-cli alias -- "$0")"

이제 새로운 쉘을 열면 위 3가지 명령어에 대한 별칭을 사용할 수 있게 된다. ?? 명령어는 Codex CLI의 영향을 받았다고 한다.

  • ?? -> github-copilot-cli what-the-shell
  • git? -> github-copilot-cli git-assist
  • gh? -> github-copilot-cli gh-assist

GitHub Copilot for CLI의 사용

쉘 명령어(??)

쉘 명령어는 안 쓰던 건 까먹어서 구글링해서 쓰곤 하는데 이런 부분을 상당히 해소해 준다.

예를 들어 OS 버전을 확인해 본다고 해보자.(안타깝게도 한국어는 알아듣지 못한다.)

$ ?? show OS version

 ──────────────────── Command ────────────────────

cat /etc/os-release

 ────────────────── Explanation ──────────────────

○ cat is used to print the contents of a file to the terminal.
  ◆ /etc/os-release is the path to the file containing the OS release information.

❯ Run this command
  Revise query
  Cancel

?? show OS version이라고 입력하자 cat /etc/os-release라는 명령어를 만들어 주었고 아래는 해당 명령어에 대한 추가 설명이 나온다. Run this command를 선택하고 엔터를 누르면 아래처럼 정말 실행할 것인지를 묻는다.

$ ?? show OS version

 ──────────────────── Command ────────────────────

cat /etc/os-release

 ────────────────── Explanation ──────────────────

○ cat is used to print the contents of a file to the terminal.
  ◆ /etc/os-release is the path to the file containing the OS release information.


  This will execute the suggested command in your shell.
  Are you sure? (y/N)

y를 누르면 실행되는데 약간 귀찮기는 하다. 아마도 파일 삭제 같은 위험한 명령어를 실행할 수도 있으므로 한번 확인 절차를 넣는 게 아닐까 싶은데 앞에서 명령어 실행을 선택하고 왔으니 바로 실행해도 되지 않을까 싶다.

$ ?? show OS version

 ──────────────────── Command ────────────────────

cat /etc/os-release

 ────────────────── Explanation ──────────────────

○ cat is used to print the contents of a file to the terminal.
  ◆ /etc/os-release is the path to the file containing the OS release information.

  Hold on, executing commmand...
[bat error]: '/etc/os-release': No such file or directory (os error 2)

하지만 cat /etc/os-release는 Linux에서 사용하는 방식이므로 macOS에는 이런 파일이 없어서 명령어를 실행해도 오류가 난다. ChatGPT에 다들 익숙해지고 있다시피 구체적인 요구사항을 주는 게 좋고 나온 명령어가 맞는지 아닌지 검증도 필요하다. 원하는 명령어가 아닐 경우에 추가 정도를 더 제공할 수 있다.

$ ?? show OS version

 ──────────────────── Command ────────────────────

cat /etc/os-release

 ────────────────── Explanation ──────────────────

○ cat is used to print the contents of a file to the terminal.
  ◆ /etc/os-release is the path to the file containing the OS release information.

  Run this command
❯ Revise query
  Cancel

아까 이 단계에서 Run this command 대신 Revise query를 선택하면 쿼리를 수정할 수 있다.

$ ?? show OS version

 ──────────────────── Command ────────────────────

cat /etc/os-release

 ────────────────── Explanation ──────────────────

○ cat is used to print the contents of a file to the terminal.
  ◆ /etc/os-release is the path to the file containing the OS release information.

 ──────────────────── Revision ────────────────────

Enter your revision: for macos

Enter your revision라는 말이 좀 헷갈리는데 전체 문장을 다 입력할 필요는 없고 추가 정보만 입력하면 된다. 위에서는 macOS에서 OS 버전을 보고 싶었으므로 for macos라고 입력했다.

$ ?? show OS version

 ───────────────────── Query ─────────────────────

1) show OS version 2) for macos

 ──────────────────── Command ────────────────────

sw_vers

 ────────────────── Explanation ──────────────────

○ sw_vers is used to print information about the current macOS version.

❯ Run this command
  Revise query
  Cancel

이제 제대로 된 명령어가 나왔다. Run this command를 선택하면 명령어가 실행되고 OS 버전이 나온다.

$ ?? show OS version for macOS

 ──────────────────── Command ────────────────────

sw_vers

 ────────────────── Explanation ──────────────────

○ sw_vers is used to print information about the current macOS version.

  Hold on, executing commmand...
ProductName:    macOS
ProductVersion:   13.2.1
BuildVersion:   22D68

글이라서 좀 장황했지만, GitHub Copilot for CLI의 인터페이스가 어떻게 동작하는지 보기 위해서 단계별로 찬찬히 봤고 모든 명령어는 다 이와 똑같이 동작한다.

좀 더 복잡한 요구사항을 전달해 보자. 현재 폴더에서 "terraform"이라는 문자열이 들어있는 모든 JS 파일을 찾도록 했다.

$ ?? list only js files contain "terraform" in contents

 ──────────────────── Command ────────────────────

find . -name "*.js" | xargs grep -l "terraform"

 ────────────────── Explanation ──────────────────

○ find is used to list files.
  ◆ -name "*.js" stipulates that we search for files ending in .js.
○ | xargs passes the list of files to the next command.
  ◆ grep is used to search for a pattern in a file.
    ◇ -l means we only want the file names, not the lines that contain the pattern.
    ◇ "terraform" is the pattern we search for.

❯ Run this command
  Revise query
  Cancel

특정 포트를 사용하는 프로세스를 찾아보았다.

$ ?? who use 3000 port

 ──────────────────── Command ────────────────────

sudo lsof -i :3000

 ────────────────── Explanation ──────────────────

○ sudo is used to run a command with elevated rights, to e.g. change system files.
  ◆ lsof is used to list open files.
    ◇ -i :3000 specifies that we want to list all files that are listening on port 3000.

❯  Run this command
   Revise query
   Cancel


Git(git?)

git 명령어는 git?를 사용한다. 사용 방법은 똑같으니 몇 가지 예시만 살펴보자. 다음은 커밋 히스토리에서 author 별로 커밋 카운트를 세어봤다.

git? commit count by author

 ──────────────────── Command ────────────────────

git shortlog -s -n

 ────────────────── Explanation ──────────────────

○ git shortlog is used to list the commits in the current branch.
  ◆ -s specifies that we want to list the number of commits per author.
  ◆ -n specifies that we want to sort the authors by the number of commits

main 브랜치만의 커밋 히스토리를 출력해 봤다.

$ git? show history main branch only

 ──────────────────── Command ────────────────────

git log --oneline main

 ────────────────── Explanation ──────────────────

○ git log is used to list commits.
  ◆ --oneline specifies that we want a short listing.
  ◆ main specifies that we want to list the commits on the main branch

다음은 좀 잘못 나온 예시이다. 난 상대적 시간 대신 절대 시간으로 출력하길 원했지만 --date 옵션에 relative는 있지만 absolute는 없다. isolocal같은 옵션을 주었어야 했지만 그렇게까진 해주지 않았다.

$ git? show history with commit sha 3 length, author, absolute date and email

 ──────────────────── Command ────────────────────

git log --pretty=format:"%h %an %ad %ae" --abbrev-commit --date=absolute

 ────────────────── Explanation ──────────────────

○ git log is used to list commits.
  ◆ --pretty=format:"%h %an %ad %ae" specifies the format of the output.
    ◇ %h is the abbreviated commit hash.
    ◇ %an is the author name.
    ◇ %ad is the date of the commit.
    ◇ %ae is the author email.
  ◆ --abbrev-commit specifies that we want to abbreviate the commit hash.
  ◆ --date=absolute specifies that we want to use absolute dates.


GitHub CLI(gh?)

GitHub CLI는 아주 유용하기 때문에 애용해서 쓰는 편이지만 모든 명령어를 다 아는 것도 아니고 gh로 GitHub API도 사용할 수 있기 때문에 API를 사용할 때는 GitHub 문서를 봐야 했었는데 이럴 때도 유용할 것 같다.

다음은 github/docs 저장소의 워크플로우 목록을 조회하도록 했는데 API 조회후 jq로 데이터 정리까지 잘해주었다.

$ gh? show workflow id and name from workflow list of github/docs

 ──────────────────── Command ────────────────────

gh api repos/github/docs/actions/workflows | jq '.workflows | map({id: .id, name: .name}) | .[]'

 ────────────────── Explanation ──────────────────

○ gh api is used to issue GitHub API requests.
  ◆ repos/github/docs/actions/workflows specifies that we want to list the workflows of the github/docs
repository.
  ◆ | jq uses the jq tool to process the response using a series of filters.
    ◇ .workflows selects the list of workflows in the response.
    ◇ | map(...) builds a new object for each workflow in the list with the following elements.
      ▪ id build from the existing id field.
      ▪ name is taken from the existing name field.
    ◇ | .[] selects the first element of the list.

현재 브랜치를 기준으로 Pull Request를 생성하는 명령어를 작성했다.

$ gh? open pr from current branch

 ──────────────────── Command ────────────────────

CUR_BRANCH=$(git branch --show-current) gh pr create --fill --base=main --head=$CUR_BRANCH

 ────────────────── Explanation ──────────────────

○ CUR_BRANCH=$(...) is used to assign the output of the command inside $(...) to the variable CUR_BRANCH.
  ◆ git branch --show-current prints the name of the current branch.
○ gh pr create is used to create a new PR.
  ◆ --fill means that we want to fill in the PR title and description from the commit message.
  ◆ --base=main specifies that we want to merge into the main branch.
  ◆ --head=$CUR_BRANCH specifies that we want to merge from the current branch.


실제로 사용하면서 정확도를 좀 봐야겠지만(테스트로 해서 그런지 중간중간 동작하지 않는 명령어도 꽤 많이 나왔다.) 명령어 같은 경우는 검색해서 찾는 경우가 많으므로 GitHub Copilot만큼이나 꽤 유용할 것으로 보인다. 특히 설명도 잘 나와서 CLI를 배우는 데도 효과적일 것으로 생각된다. 한국어가 안 되는 건 아쉽지만, 터미널에서 한/영 전환하는 것도 귀찮긴 하니까 그렇게 까지 나쁘진 않다.

2023/03/31 20:51 2023/03/31 20:51