Hi there! 👋 I’m Tony Aldon a passionate Emacs and AI enthusiast.
If you want to learn how to build a ChatGPT client for Emacs integrating the OpenAI API, this course is for you!
Through 18 engaging lessons, 2.5 hours video content and a detailed PDF companion you’ll learn how to build a fully functional Emacs package from scratch and you’ll know how to use the OpenAI API.
It can help if you know a little bit of Emacs Lisp, but this is not a requirement as we’ll meticulously write, review, and comment on each line of code.
In this course, we’ll build chatgpt.el, a
package that lets you send prompts to ChatGPT directly from Emacs using
the OpenAI API. ️ Simply call the chatgpt command, enter
your prompt in the dedicated buffer, press C-c C-c, and
receive your response in an appended buffer seamlessly.
Beyond its simplicity, chatgpt.el offers these key
features:
~/.authinfo.gpg for secure storage or
from the plaintext ~/.authinfo file.
M-p and M-n.
We kick things off by sending our very first request to OpenAI using the
curl command. We craft a simple JSON request, send it off,
and see how ChatGPT responds. This gets us familiar with the basics of
the Chat Completion API.
Next, we explore how to receive responses from OpenAI as a continuous stream. Instead of waiting for the full reply, we get it in real-time chunks.
Here, we learn how to customize our interactions by tweaking developer and system messages.
In this lesson, we dive into using assistant messages to keep the context alive across multiple turns.
Time to write some Emacs Lisp! Here, we introduce the
make-process function to run shell commands asynchronously
within Emacs.
make-processmake-processBuilding on what we’ve learned, we now send our first OpenAI request directly from Emacs Lisp.
chatgpt-send Command in chatgpt.el File
In this lesson, we refactor the chatgpt-send function for
better organization and introduce a dedicated variable for our OpenAI
API key.
chatgpt-send with
chatgpt-command
chatgpt-api-key to hold OpenAI API Keychatgpt-command Function SignatureNo more static prompts! Here, we make our requests dynamic by pulling prompts from the current buffer.
chatgpt-send
In this lesson, we learn how to parse JSON responses and format them
using markdown-mode within Emacs.
json-readmap-nested-elt
markdown-modeHere, we set up our package to save every request and response to organized directories on disk. With timestamped files, we can easily browse through past interactions.
chatgpt-send with
chatgpt-request
chatgpt-send with
chatgpt-callback
chatgpt-send with
chatgpt-json-encode
We set up the *chatgpt* buffer to enter our prompts,
positioning it at the bottom of the frame. By defining
chatgpt-mode, we customize this buffer’s behavior and
appearance, making it the perfect spot to interact with ChatGPT
seamlessly within Emacs.
chatgptchatgpt-modechatgpt-model Variablechatgpt-mode Oncechatgpt-dir in chatgpt-modechatgpt-mode-map keymap
In this lesson, we tweak our functions so that once ChatGPT replies, the
*chatgpt[requests]* buffer pops up automatically.
chatgpt-send into
chatgpt-send-request
Sometimes things go wrong. Here, we update our package to gracefully handle API errors from OpenAI. Whether it’s a wrong model or a connection hiccup, we catch these errors, display meaningful messages, and log them for future reference.
In this lesson, we introduce timestamp files for each request. These little helpers will help us later to sort and manage our interactions chronologically.
chatgpt-timestamp Functionchatgpt-requests Function
Here, we explore Emacs’s built-in ring package that we’ll
use later to manage our prompt history efficiently. Rings are perfect
for handling recent interactions, using them will allow us to cycle
through prompts effortlessly.
Now, we put rings into action by adding a prompt history feature. With
convenient shortcuts like M-p and M-n, we’ll
be able to navigate through our past prompts with ease.
M-p and M-n in
chatgpt-mode-map
chatgpt-history and chatgpt-push
chatgpt-previous Commandchatgpt-historychatgpt-history from DiskIn this lesson, we create a simple waiting widget in the mode line that flashes while we wait for ChatGPT’s response.
Finally, we learn how to handle our OpenAI API key securely using
Emacs’s ~/.authinfo and ~/.authinfo.gpg files.
chatgpt-command Function~/.authinfo File