/chatgpt-shell

ChatGPT and DALL-E Emacs shells + Org babel 🦄 + a shell maker for other providers

Primary LanguageEmacs LispGNU General Public License v3.0GPL-3.0

👉 Support this work via GitHub Sponsors

chatgpt-shell

ChatGPT and DALL-E Emacs shells + Org Babel.

Includes shell-maker, a way to create shells for any service (local or cloud).

Note

This is very much an experimental proof of concept, possibly incomplete, or maybe with some rough edges. Pull requests with improvements or fixes totally welcome.

Install

  • Load (require 'chatgpt-shell)
  • Load (require 'dall-e-shell)

Set OpenAI key

You’ll first need to get a key from OpenAI.

ChatGPT key

As function

;; if you are using the "pass" password manager
(setq chatgpt-shell-openai-key
      (lambda ()
        ;; (auth-source-pass-get 'secret "openai-key") ; alternative using pass support in auth-sources
        (nth 0 (process-lines "pass" "show" "openai-key"))))

;; or if using auth-sources, e.g., so the file ~/.authinfo has this line:
;;  machine api.openai.com password OPENAI_KEY
(setq chatgpt-shell-openai-key
      (auth-source-pick-first-password :host "api.openai.com"))

;; or same as previous but lazy loaded (prevents unexpected passphrase prompt)
(setq chatgpt-shell-openai-key
      (lambda ()
        (auth-source-pick-first-password :host "api.openai.com")))

Manually

M-x set-variable chatgpt-shell-openai-key

As variable

(setq chatgpt-shell-openai-key "my key")

DALL-E key

Same as ChatGPT, but use dall-e-shell-openai-key variable.

Launch

Launch with M-x chatgpt-shell or dall-e-shell.

Clear buffer

Type clear as a prompt.

ChatGPT> clear

Alternatively, use either M-x chatgpt-shell-clear-buffer or M-x comint-clear-buffer.

Saving and restoring (experimental)

Save with M-x shell-maker-save-session-transcript and restore with M-x chatgpt-shell-restore-session-from-transcript.

Streaming

chatgpt-shell can either wait until the entire response is received before displaying, or it can progressively display as chunks arrive (streaming).

(setq chatgpt-shell-chatgpt-streaming nil) to disable streaming. Streaming is enabled by default.

Explain code in region

M-x chatgpt-shell-explain-code

There are other functions to act on region. Browse all available via M-x.

ChatGPT org babel

Load (require 'ob-chatgpt-shell) and invoke (ob-chatgpt-shell-setup).

#+begin_src chatgpt-shell
  Hello
#+end_src

#+RESULTS:
: Hi there! How can I assist you today?

DALL-E org babel

Load (require 'ob-dall-e-shell) and invoke (ob-dall-e-shell-setup).

#+begin_src dall-e-shell
  Pretty clouds
#+end_src

#+RESULTS:
[[file:/var/folders/m7/ky091cp56d5g68nyhl4y7frc0000gn/T/1680644778.png]]

Customizations

chatgpt-shell-default-promptsList of prompts to choose from in the minibuffer.
chatgpt-shell-model-versionThe used ChatGPT OpenAI model.
chatgpt-shell-streamingWhether or not to stream ChatGPT responses (experimental).
chatgpt-shell-system-promptThe system message helps set the behavior of the assistant.
chatgpt-shell-language-mappingMaps external language names to Emacs names.
chatgpt-shell-model-temperatureWhat sampling temperature to use, between 0 and 2, or nil.
chatgpt-shell-openai-keyOpenAI key as a string or a function that loads and returns it.
chatgpt-shell-request-timeoutHow long to wait for a request to time out.
chatgpt-shell-display-functionFunction to display new shell. Can be set to `display-buffer’ or custom function.
chatgpt-shell-read-string-functionFunction to read strings from user.
chatgpt-shell-on-response-functionFunction to automatically execute after last command output.
dall-e-shell-openai-keyOpenAI key as a string or a function that loads and returns it.
dall-e-image-sizeThe default size of the requested image as a string.
dall-e-model-versionThe used DALL-E OpenAI model.

There are more. Browse via M-x set-variable

chatgpt-shell-display-function (with custom function)

If you’d prefer your own custom display function,

(setq chatgpt-shell-display-function #'my/chatgpt-shell-frame)

(defun my/chatgpt-shell-frame (bname)
  (let ((cur-f (selected-frame))
        (f (my/find-or-make-frame "chatgpt")))
    (select-frame-by-name "chatgpt")
    (pop-to-buffer-same-window bname)
    (set-frame-position f (/ (display-pixel-width) 2) 0)
    (set-frame-height f (frame-height cur-f))
    (set-frame-width f  (frame-width cur-f) 1)))

(defun my/find-or-make-frame (fname)
  (condition-case
      nil
      (select-frame-by-name fname)
    (error (make-frame `((name . ,fname))))))

Thanks to tuhdo for the custom display function.

Commands

dall-e-shellStart a DALL-E shell.
chatgpt-shellStart a ChatGPT shell.
chatgpt-shell-promptMake a ChatGPT request from the minibuffer.
chatgpt-shell-describe-codeDescribe code from region using ChatGPT.
chatgpt-shell-eshell-summarize-last-command-outputAsk ChatGPT to summarize the last command output.
chatgpt-shell-eshell-whats-wrong-with-last-commandAsk ChatGPT what’s wrong with the last eshell command.
chatgpt-shell-mark-outputMark last or current output.
chatgpt-shell-restore-session-from-transcriptRestore session from transcript.
chatgpt-shell-save-session-transcriptSave shell transcript to file.
chatgpt-shell-send-and-review-regionSend region to ChatGPT, review before submitting.
chatgpt-shell-send-regionSend region to ChatGPT.

There are more. Browse all available via M-x.

shell-maker

There are currently two shell implementations (ChatGPT and DALL-E). Other services (local or cloud) can be brought to Emacs as shells. shell-maker can help with that.

shell-maker is a convenience wrapper around comint mode.

Both chatgpt-shell and dall-e-shell use shell-maker, but a basic implementation of a new shell looks as follows:

(require 'shell-maker)

(defvar greeter-shell--config
  (make-shell-maker-config
   :name "Greeter"
   :execute-command
   (lambda (command _history callback error-callback)
     (funcall callback
              (format "Hello \"%s\"" command)
              nil))))

(defun greeter-shell ()
  "Start a Greeter shell."
  (interactive)
  (shell-maker-start greeter-shell--config))

Other packages

👉 Support this work via GitHub Sponsors