· 14 min read
Playing with Copilot CLI on top of Warp terminal
The power of GitHub Copilot embedded in your favourite terminal, enhanced by the Warp AI assistant
I recently got access to the new Copilot CLI, which basically gives you the full power of GitHub Copilot but in your favourite terminal so… time to give it a try!
As of today, the tool is in the waitlist stage. If you don’t have access yet, you can request it on the Copilot for CLI page on GitHub Next. An active Copilot subscription is required.
Setup
Did you get access? Yaay! Here’s how to get started:
- Install the CLI as a regular node package:
npm install -g @githubnext/github-copilot-cli
- Run the command
github-copilot-cli auth
to authenticate with your GitHub account - Setup the aliases with
eval "$(github-copilot-cli alias -- "$0")"
Aliases
Why set up aliases? I don’t think you want to type github-copilot-cli
every time you want to use the tool, as easy as that!
If you ran the command on step 3 you will have them available, but only in the current session! To have them globally available make sure to past the command eval "$(github-copilot-cli alias -- "$0")"
in your .bashrc
or .zshrc
file, depending on the shell you’re using.
For completeness, there’s an extra reason besides having convenient aliases and it’s explained in the documentation, in short, it makes the tool work better.
After all this explanation, here’s the list of aliases you’ll get:
??
: Ask for a generic shell commandgit?
: Ask for agit
commandgh?
: Ask for a GitHub CLI command
Test run
Since I recently started using the Warp terminal which also has an AI assistant, I thought it would be fun to try both at the same time!
These days we’re flooded with AI-assisted tools, and they’re all great, but at some point, we should find out which one works best for each one of us.
Let’s warm up with an easy one, the good old getting rid of the node_modules
folder.
Prompt
delete node modules of this project
Copilot CLI
After about a second the tool suggested the expected rm -rf node_modules
, and you can see below the explanation was still pending.
One more second later and also the explanation arrived.
It’s time to select with the up/down arrows if you want to run the command, revise the query or cancel and get back to the prompt.
It’s worth noting that after selecting the first option it’s still not immediately executed and you get the known (y/N) question with capital N.
At first, this made me think “No” was automatically selected when pressing Enter but looks like it’s not the case.
I pressed y
and the command was executed. You can see the output here: https://app.warp.dev/block/Yy5mEuxoMJAoq6VScNqTJa
Warp
The ??
counterpart in Warp is #
, so let’s use it to ask Warp the same question! The first difference I see is that as soon as you type #
the AI panel appears.
Press Enter and after about a second the command appears under “Suggested command”.
With Cmd+Enter
the command is not executed but actually put into the terminal, so you can still edit it before running it.
Speaking of the explanation, you can request it by clicking on the “Explain how this works” button.
A side panel will appear and by pressing Enter again you will see the in-depth explanation.
Refining the suggestion
AI tools are far from being perfect, you would not let them run commands by themselves without checking them first and in fact, both tools we tried here have a double step for confirmation and let you refine the command before running it.
It’s supposed to be a suggestion after all, not necessarily a command to immediately run.
Speaking of refining the command, Copilot CLI uses an approach that I don’t really like. It’s not possible to edit the command directly, you can only change the query and get a new suggestion. I mean, it leverages even more the AI power but sometimes you just want to edit the command directly.
But maybe it’s just my personal opinion there. Please let me know in the comments which approach you like the most, between having a refined command by the AI or being able to edit it directly.
Command explanation
Once more, we’re talking about suggestions here, so an explanation is always welcome. And again, we see two different approaches.
Copilot CLI gives you the explanation as soon as the suggestion is ready, while Warp gives you the command first and then you can request the explanation manually, if you want.
The explanation isn’t at the same depth though! Copilot arrives faster but with a really concise and short explanation, while Warp requires an extra user interaction but goes way more in-depth.
This time I don’t have a strong feeling about either approach so I’m once more asking for your opinion.
A short command
At the beginning of the article I mentioned you might want to edit your .bashrc
or .zshrc
file to have the aliases available globally, but how can you do that? Let’s ask the AI!
(well, you need it already up and running before asking, but you get the point!)
Prompt
edit default zsh config
Copilot CLI
At first, it suggested nano ~/.zshrc
which is a good start, but I wanted to use VS Code instead. This time I went for “Revise query” and asked for vscode instead.
It regenerated the suggestion with code ~/.zshrc
which is exactly what I wanted.
Full output: https://app.warp.dev/block/mnMviqjfJE2WUsoEXfd4RN
Warp
The same goes for Warp, the first suggestion was nano ~/.zshrc
.
I mean, looks like these Artificial Intelligence tools are not subscribed to my YouTube channel, otherwise, they would know I use Visual Studio Code!
A tricky one
Let’s level up a little bit!
Prompt
find all images inside content/blog and add them to a zip called blogImages
Copilot CLI
Copilot only includes png
images and passes them to the zip
command with the well-known xargs
.
find content/blog -name "*.png" | xargs zip blogImages
Again, the explanation is really really short but isn’t missing anything in particular.
Warp
Warp includes both png
and jpg
images and passes them to the zip
command with a zip-specific flag that is -@
.
find content/blog -name "*.jpg" -o -name "*.png" | zip blogImages -@
The explanation here as usual is longer and with more “natural language”, as if a human was explaining it to you.
This command finds all files with the extension “.jpg” or “.png” in the directory “content/blog” and pipes the output to the
zip
command. Thezip
command creates a zip file named “blogImages.zip” and adds the files from the standard input (indicated by the-@
option).In other words, this command creates a zip file named “blogImages.zip” containing all the “.jpg” and “.png” files in the “content/blog” directory.
Dealing with a husky error
When working on an Open Source project I noticed I had this message after each commit:
hint: The '.husky/pre-commit' hook was ignored because it's not set as executable.
hint: You can disable this warning with `git config advice.ignoredHook false`.
Prompt
how can I fix this error: hint: The ‘.husky/pre-commit’ hook was ignored because it’s not set as executable. hint: You can disable this warning with
git config advice.ignoredHook false
.
Copilot CLI
──────────────────── Command ────────────────────
chmod +x .husky/pre-commit
────────────────── Explanation ──────────────────
○ chmod is used to change the permissions of a file.
◆ +x adds the executable permission.
◆ .husky/pre-commit is the file whose permissions we want to change.
Warp
chmod +x .husky/pre-commit
Same command, so I asked to explain it:
The output you received indicates that the commit was successful and a new file
test.txt
was created. However, there is a warning message about the.husky/pre-commit
hook not being set as executable.This warning message is related to Git hooks, which are scripts that run automatically before or after certain Git commands. The
.husky/pre-commit
hook is a pre-commit hook that is used by the Husky package to run scripts before each commit.To fix the warning message, you can make the
.husky/pre-commit
hook executable by running the following command in your terminal:
chmod +x .husky/pre-commit
This command sets the executable bit for the
pre-commit
file in the.husky
directory, which allows Git to run the script before each commit.After making the
.husky/pre-commit
hook executable, you can continue working with Git as usual.
A really good one, it was exactly what I was looking for!
Looking for something in natural language
Prompt
help me find PII in the blog articles in this folder
Copilot CLI
I’ve been quite generic here, I didn’t specify what PII is and I didn’t specify what I want to do with it. Copilot suggested a grep
command that looks for email
, phone
or address
in all the .md
files in the current directory which makes sense.
──────────────────── Command ────────────────────
for file in *.md; do
grep -E "(email|phone|address)" $file;
done
────────────────── Explanation ──────────────────
○ The for loop iterates over a list of items and executes its body for each, using the loop variable $file.
◆ The list of items is *.md which means all files ending in .md in the current directory.
○ The loop body executes one command for each file:
◆ grep is used to search for a pattern in a file.
◇ -E means we want to use extended regular expressions.
◇ "(email|phone|address)" is the pattern we search for.
◇ $file is the file we search in.
Warp
Warp gave me this long regex and ended up with path/to/folder
which is not exactly I wanted, but I can just accept the command and change the path manually.
grep -r -E "\b([0-9]{9}|[0-9]{3}-[0-9]{2}-[0-9]{4}|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,})\b" /path/to/folder
However, I had no idea what that regex was so it’s once again time to ask for an explanation:
This is a command that uses the
grep
utility to search for a regular expression pattern in all files under the/path/to/folder
directory recursively.Here’s a breakdown of the command:
grep
is a command-line utility that searches for patterns in files.-r
is an option that tellsgrep
to search recursively in all subdirectories under the specified directory.-E
is an option that tellsgrep
to use extended regular expressions."\b([0-9]{9}|[0-9]{3}-[0-9]{2}-[0-9]{4}|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,})\b"
is the regular expression pattern thatgrep
searches for. This pattern matches three types of strings:- A 9-digit number
- A social security number in the format
XXX-XX-XXXX
- An email address in the format
username@domain.com
/path/to/folder
is the directory wheregrep
starts searching for files.So, when you run this command,
grep
searches for all files under the/path/to/folder
directory recursively and prints out all lines that match the regular expression pattern. The regular expression pattern matches any line that contains a 9-digit number, a social security number, or an email address.
This makes much more sense now!
Moving files around
For the next test I wanted to actually change some files. I already have a zip with them so let’s use the AIs to suggest me the commands to move things around!
Prompt
Extract the content of tmp.zip and put it in a new folder called temp in my root directory
Copilot CLI
──────────────────── Command ────────────────────
unzip tmp.zip -d ~/temp
────────────────── Explanation ──────────────────
○ unzip is used to extract files from a zip archive.
◆ tmp.zip is the name of the zip archive.
◆ -d ~/temp specifies that we want to extract the files to the ~/temp folder.
Nice and easy!
Warp
unzip ~/Downloads/tmp.zip -d ~/temp
Not sure why it assumed the zip was inside download, but again Warp lets me manually edit the command so I just fix the path and that’s it!
Anonymize some data
Now that I’ve got some files in my temp folder, let’s try to anonymize them!
Prompt
Find all PII and anonymize them
Copilot CLI
──────────────────── Command ────────────────────
find . -name "*.py" | xargs sed -i "s/([0-9]{3}) [0-9]{3}-[0-9]{4}/(xxx) xxx-xxxx/g"
────────────────── Explanation ──────────────────
○ find is used to list files.
◆ -name "*.py" stipulates that we search for files ending in .py.
○ | xargs passes the list of files to the next command.
◆ sed is used to search and replace text in files.
◇ -i specifies that we want to replace the text in the files themselves.
◇ "s/([0-9]{3}) [0-9]{3}-[0-9]{4}/(xxx) xxx-xxxx/g" is the search and replace pattern.
▪ s means we want to search and replace.
▪ ([0-9]{3}) [0-9]{3}-[0-9]{4} is the search pattern.
▫ ([0-9]{3}) means we want to match three digits and capture them in a group.
▫ means we want to match a space.
▫ [0-9]{3}-[0-9]{4} means we want to match three digits, a dash, and four digits.
▪ (xxx) xxx-xxxx is the replacement pattern.
▫ (xxx) means we want to insert the string (xxx) into the text.
▫ means we want to insert a space.
▫ xxx-xxxx means we want to insert the string xxx-xxxx into the text.
▪ g means we want to replace all occurrences, not just the first one.
This time Copilot did a bold assumption, only looking for .py
files. I used “Revise Query” to tell him “Files are in markdown” and it updated the first command with find . -name "*.md"
.
Warp
Warp’s take is consistent to the previous one in using a regex for the search, but by using grep it’s not actually changing the files, just printing the lines that match the regex.
grep -rEIi '([0-9]{3}-[0-9]{2}-[0-9]{4}|[0-9]{3}.[0-9]{2}.[0-9]{4}|[0-9]{9})' . | sed -E 's/([0-9]{3}-[0-9]{2}-)[0-9]{4}/\1XXXX/g; s/([0-9]{3}.[0-9]{2}.)[0-9]{4}/\1XXXX/g; s/([0-9]{9})/XXXXXXXXX/g'
This makes me think the prompt wasn’t clear enough, so I try to rephrase it:
Find all PII in this folder and anonymize them in place
find . -type f -exec sed -i 's/[0-9]\{3\}-[0-9]\{2\}-[0-9]\{4\}/XXX-XX-XXXX/g' {} +
I was deliberately vague about what a PII is but it starts to make sense. Let’s give it another try with a more specific prompt:
Find all emails and phone numbers in this folder and anonymize them in place
find . -type f -exec sed -i -E 's/[[:alnum:]+\.\_\-]+@[[:alnum:]+\.\_\-]+/[ANONYMIZED_EMAIL]/g; s/[0-9]{3}-[0-9]{3}-[0-9]{4}/[ANONYMIZED_PHONE]/g' {} +
I ran it and… sed: RE error: illegal byte sequence
(see https://app.warp.dev/block/31KX08qIi09BN1PS6GtAkA)
Well well well… let’s ask Warp AI for an explanation:
The error message
sed: RE error: illegal byte sequence
indicates thatsed
encountered a byte sequence that it cannot handle. This error can occur whensed
tries to process a file that contains non-ASCII characters or when the file encoding is not compatible with the current locale.To fix this error, you can try adding the
-i''
option to thesed
command to create a backup of the original file before making any changes. This option can help avoid issues with file encoding and non-ASCII characters.Here’s the updated command:
find . -type f -exec sed -i'' -E 's/[[:alnum:]+\.\_\-]+@[[:alnum:]+\.\_\-]+/[ANONYMIZED_EMAIL]/g; s/[0-9]{3}-[0-9]{3}-[0-9]{4}/[ANONYMIZED_PHONE]/g' {} +
This command should create a backup of each file before making any changes and replace all email addresses and phone numbers with
[ANONYMIZED_EMAIL]
and[ANONYMIZED_PHONE]
, respectively.If the error persists, you can try specifying the file encoding explicitly using the
-e
option. For example, if the file encoding is UTF-8, you can use the following command:find . -type f -exec sed -i'' -e 's/[[:alnum:]+\.\_\-]+@[[:alnum:]+\.\_\-]+/[ANONYMIZED_EMAIL]/g; s/[0-9]{3}-[0-9]{3}-[0-9]{4}/[ANONYMIZED_PHONE]/g' {} +
This command should replace all email addresses and phone numbers with
[ANONYMIZED_EMAIL]
and[ANONYMIZED_PHONE]
, respectively, while handling non-ASCII characters correctly.
A lot of context there, but actually the first line already made me realize that there are also images in that folder… time for a new prompt to restrict the scope of the search to markdown files only!
Find all emails and phone numbers in markdown files in this folder and anonymize them in place
And this time I got a working command:
find . -name "*.md" -type f -exec sed -E -i '' 's/[[:alnum:]+\.\_\-]+@[[:alnum:]+\.\_\-]+/[email]/g; s/\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/[phone]/g' {} +
The winner is…
There has to be a winner?
Both tools are really fast and accurate but have a slightly different user experience.
I’m personally still not too confident in letting an AI run commands on my machine without checking them first, so I like that Warp lets me open a chat where I can discuss with the AI about the command and ask for an explanation, whereas Copilot just gives me a brief explanation of the command and that’s it.
I also have to mention that Warp is actually an entire terminal so you can have way more interactions and features while Copilot is just a CLI tool… so you can benefit from both!
Since I’m using Warp anyway, it’s just a matter of starting the command with either #
or ??
depending on the AI experience I’m looking for and I’m already good to go!
What about you? Have you tried any of these tools? What’s your experience with them? Let me know in the comments!
Hello! My name is Leonardo and as you might have noticed, I like to talk about Web Development and Open Source!
I use GitHub every day and my favourite editor is Visual Studio Code... this might influence a little bit my conent! :D
If you like what I do, you should have a look at my YouTube Channel!
Let's get in touch, feel free to send me a DM on Twitter!