ColeDrain
Posted on March 25, 2023
Introduction:
Hello there amigo 👋.
In this tutorial, I will show you how to create a CLI app that allows you to interact with ChatGPT from the command line. The app, named "ChatShell", will allow users to ask for shell commands for specific tasks or chat with ChatGPT directly. We'll be using the Go programming language and Cobra CLI library to create our CLI app and the go-openai library to interact with OpenAI's GPT-3 API.
Please do give a thumbs-up, if this was insightful in any way.
Prerequisites:
- Go programming language installed (version 1.20.2 or higher)
- Cobra CLI library installed
- go-openai library installed
- Viper library installed (for config and environment vars)
- An OpenAI API key
End Goal:
- Able to run shell command of form:
chatshell ask "how to delete a local branch ?"
chatshell ask -c "when was gpt first built ?"
Steps:
A. Set up the project structure
Create a new directory for the project and navigate to it
$ mkdir chatshell
$ cd chatshell
Initialize a new Go module
$ go mod init github.com/{your_username}/chatshell
# note: replace {your_username} with actual github username
Install the Cobra CLI library and go-openai library
$ go install github.com/spf13/cobra-cli@latest
$ go get -u github.com/sashabaranov/go-openai
$ go get github.com/spf13/viper
B. Create the CLI app
cobra-cli helps generate boilerplates for your cli app automatically, this speeds up development.
Use the Cobra CLI to generate the basic structure of the CLI app:
$ cobra-cli init
This will generate the basic structure of the CLI app, including a main.go file, a cmd directory, and a LICENSE file.
You can have a look at the code if you're familiar with cobra.
C. Implement the 'ask' command
Once again we will call on our friend (cobra-cli)
cobra-cli add ask
This will generate a file ask.go which will contain the implementation of the 'ask' command. We have to finetune the boilerplate to our need, below is finetuned code well commented for understanding.
Import necessary packages
/*
Copyright © 2023 Ugochukwu Onyebuchi <pyvinci@gmail.com>
*/
package cmd
import (
"context"
"fmt"
"os"
"runtime"
"github.com/spf13/cobra"
"github.com/spf13/viper"
openai "github.com/sashabaranov/go-openai"
)
Next intialize the askCmd
Use: a short description of how to use the ask command, in our case we expect ask to be followed by a text in quotes
Short: a short description of the ask command
Long: a longer description
Args: we specify we only want one argument, which is a text in quotes
Run: we specify the function to be called, this function will handle the business logic.
// askCmd represents the ask command
var askCmd = &cobra.Command{
Use: "ask [text]",
Short: "ask ChatGPT",
Long: `ask is used to ask for shell commands for a particular task`,
Args: cobra.ExactArgs(1),
Run: runAsk,
}
// authToken holds your openai auth key
var authToken string
// initial operations
func init() {
// add the ask command to root
rootCmd.AddCommand(askCmd)
// add flag to enable chat mode
askCmd.PersistentFlags().BoolP("chat", "c", false, "Chat with ChatGPT")
// Read the auth token from a configuration file
viper.SetConfigName("config")
viper.AddConfigPath("$HOME/.chatshell")
viper.AddConfigPath(`%USERPROFILE%/.chatshell`)
viper.SetEnvPrefix("OPENAI")
viper.AutomaticEnv()
// Handle missing config file or auth token
if err := viper.ReadInConfig(); err == nil {
authToken = viper.GetString("OPENAI_AUTH_TOKEN")
} else {
fmt.Printf("Error reading configuration file: %v\n", err)
}
if authToken == "" {
fmt.Println("Error: OPENAI_AUTH_TOKEN environment variable not set")
os.Exit(1)
}
}
The prompt I use is a bit large: but for much correctness I get the osType using runtime.GOOS
and SHELL type using os.Getenv("SHELL")
, this will help ChatGPT give reasonable shell commands of the relevant OS, we don't want shell commands for mac whilst we are using windows.. and it also responds with "Sorry I can't seem to find a command for that", if it can find a command for your prompt. It took a while to get a good prompt as this, it's an iterative process..
// Call OpenAI and prints response
func runAsk(cmd *cobra.Command, args []string) {
client := openai.NewClient(authToken)
osType := runtime.GOOS
shell := os.Getenv("SHELL")
content := ""
chatMode, _ := cmd.Flags().GetBool("chat")
// We use the state of the flag to determine the context
if !chatMode {
content = fmt.Sprintf(`You are a very helpful shell assistant that gives users only shell commands to achieve a task, just give out only the shell command(s), and nothing else, no preamble, greetings or explanation please, just the shell command. When you can't find a command for a query/prompt/greeting respond strictly with "Sorry I can't seem to find a command for that". Start now: "%v in %v os using %v shell"`, args[0], osType, shell)
} else {
content = args[0]
}
// Get ChatGPT Response
resp, err := client.CreateChatCompletion(
context.Background(),
openai.ChatCompletionRequest{
Model: openai.GPT3Dot5Turbo,
Messages: []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleUser,
Content: content,
},
},
},
)
if err != nil {
fmt.Printf("ChatCompletion error: %v\n", err)
}
fmt.Println(resp.Choices[0].Message.Content)
}
D. Update the configuration file
For all this to work you will need your OPENAI_AUTH_TOKEN set.
Remember, we set viper to look for a config file that should contain our OPENAI_AUTH_TOKEN
Create a new directory called .chatshell in your home directory (on Windows, use %USERPROFILE% instead of $HOME):
$ mkdir ~/.chatshell
Create a new file called config.json in the .chatshell directory and add your OpenAI API key as the value for the OPENAI_AUTH_TOKEN variable:
{"OPENAI_AUTH_TOKEN":"your_api_key_here"}
E. Build the CLI app
Navigate to the project's root directory and build the app:
$ go build
This will create an executable binary called 'chatshell'.
F. Use the ChatShell CLI app
Run the chatshell binary and provide a task description as an argument:
$ ./chatshell ask "how to delete a local branch ?"
output: git branch -d <branch_name>
The app will then interact with ChatGPT and return the shell command for the given task.
You can also use the -c flag to chat with ChatGPT directly:
$ ./chatshell ask -c "When was gpt first built?"
output: GPT (Generative Pre-trained Transformer) was first introduced by OpenAI in June 2018
Conclusion:
In this tutorial, we saw how to create a Conda CLI app that interacts with ChatGPT from the command line. The ChatShell app can be used to obtain shell commands for specific tasks or chat with ChatGPT directly. Feel free to explore the provided code and the go-openai library to extend the functionality of the app or adapt it to your needs.
Repository: https://github.com/ColeDrain/chatshell
Posted on March 25, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.