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-process
make-process
Building 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-read
map-nested-elt
markdown-mode
Here, 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.
chatgpt
chatgpt-mode
chatgpt-model
Variablechatgpt-mode
Oncechatgpt-dir
in chatgpt-mode
chatgpt-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-history
chatgpt-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