diff --git a/modules/config/default/+evil-bindings.el b/modules/config/default/+evil-bindings.el index a10b31fa8..73b6d6bb8 100644 --- a/modules/config/default/+evil-bindings.el +++ b/modules/config/default/+evil-bindings.el @@ -755,6 +755,17 @@ :desc "Open in new iTerm window" "I" #'+macos/open-in-iterm-new-window)) (:when (modulep! :tools docker) :desc "Docker" "D" #'docker) + (:when (modulep! :tools llm) + (:prefix ("l" . "llm") + :desc "Add text to context" "a" #'gptel-add + :desc "Explain" "e" #'gptel-quick + :desc "Add file to context" "f" #'gptel-add-file + :desc "Open gptel" "l" #'gptel + :desc "Send to gptel" "s" #'gptel-send + :desc "Open gptel menu" "m" #'gptel-menu + :desc "Rewrite" "r" #'gptel-rewrite + :desc "Org: set topic" "o" #'gptel-org-set-topic + :desc "Org: set properties" "O" #'gptel-org-set-properties)) (:when (modulep! :email mu4e) :desc "mu4e" "m" #'=mu4e) (:when (modulep! :email notmuch) diff --git a/modules/tools/llm/README.org b/modules/tools/llm/README.org new file mode 100644 index 000000000..db9a26c95 --- /dev/null +++ b/modules/tools/llm/README.org @@ -0,0 +1,84 @@ +#+title: :tools llm +#+subtitle: When I said you needed friends, I didn't mean... +#+created: May 06, 2025 +#+since: 25.06.0 + +* Description :unfold: +This module integrates LLMs into Emacs for analyzing or generating code and +text, powered by the [[https://github.com/karthink/gptel][gptel]] package. Out of the box, ChatGPT is the default +backend, but it can talk to other LLMs given [[*Configuration][some configuration]]. + +** Maintainers +- [[doom-user:][@hlissner]] + +[[doom-contrib-maintainer:][Become a maintainer?]] + +** Module flags +/This module has no flags./ + +** Packages +- [[doom-package:gptel]] +- [[doom-package:gptel-quick]] +- [[doom-package:gptel-magit]] if [[doom-module::tools magit]] + +** Hacks +#+begin_quote +󱌣 This module's hacks haven't been documented yet. [[doom-contrib-module:][Document them?]] +#+end_quote + +** TODO Changelog +# This section will be machine generated. Don't edit it by hand. +/This module does not have a changelog yet./ + +* Installation +[[id:01cffea4-3329-45e2-a892-95a384ab2338][Enable this module in your ~doom!~ block.]] + +An OpenAI API key, paid account, and enough credits to use it is required (if +you use the OpenAI backend). To use this module with other LLMs, visit [[*Configuration][the +Configuration section]]. + +* Usage +#+begin_quote +󱌣 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]] +#+end_quote + +Check out gptel's [[https://github.com/karthink/gptel?tab=readme-ov-file#usage][usage documentation]] for details on how to use the package. + +Doom exposes these keybinds for gptel's commands: + +| Keybind | Command | Description | +|----------------+------------------------------+--------------------------------------------------| +| [[kbd:][ o l a]] | [[cmd:gptel-add]] | Add text to LLM context | +| [[kbd:][ o l e]] | [[cmd:gptel-quick]] | Explain item or selection | +| [[kbd:][ o l f]] | [[cmd:gptel-add-file]] | Add file to LLM context | +| [[kbd:][ o l l]] | [[cmd:gptel]] | Open gptel chat buffer | +| [[kbd:][ o l s]] | [[cmd:gptel-send]] | Send text before ~(point)~ (or selection) | +| [[kbd:][ o l m]] | [[cmd:gptel-menu]] | Open configuration menu for gptel | +| [[kbd:][ o l r]] | [[cmd:gptel-rewrite]] | Rewrite, refactor, or change the selected region | +| [[kbd:][ o l o]] | [[cmd:gptel-org-set-topic]] | Limit context to Org heading | +| [[kbd:][ o l O]] | [[cmd:gptel-org-set-properties]] | Store gptel config as org properties | + +This module also adds a "pre-generated message" option to magit-commit's +transient menu. Alternatively, press [[kbd:][M-g]] to generate a message in a commit +buffer. + +* Configuration +#+begin_quote +󱌣 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]] +#+end_quote + +To use this module with only ChatGPT, you only need to set ~gptel-api-key~ to your +OpenAI key. For other LLMs you'll need to call one of the ~gptel-make-*~ functions +in an ~(after! gptel ...)~ block. Examples of these calls can be found [[https://github.com/karthink/gptel?tab=readme-ov-file#other-llm-backends][in gptel's +readme]]. + +* Troubleshooting +/There are no known problems with this module./ [[doom-report:][Report one?]] + +* Frequently asked questions +/This module has no FAQs yet./ [[doom-suggest-faq:][Ask one?]] + +* TODO Appendix +#+begin_quote +󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]] +#+end_quote diff --git a/modules/tools/llm/config.el b/modules/tools/llm/config.el new file mode 100644 index 000000000..e1ae4b8e0 --- /dev/null +++ b/modules/tools/llm/config.el @@ -0,0 +1,30 @@ +;;; tools/llm/config.el -*- lexical-binding: t; -*- + +(use-package! gptel + :defer t + :config + (setq gptel-display-buffer-action nil) ; if user changes this, popup manager will bow out + (set-popup-rule! + (lambda (bname _action) + (and (null gptel-display-buffer-action) + (buffer-local-value 'gptel-mode (get-buffer bname)))) + :select t + :size 0.3 + :quit nil)) + + +(use-package! gptel-quick + :defer t + :config + (when (modulep! :tools lookup) + ;; TODO: Write `+llm-lookup-documentation-handler' + ;; (add-hook '+lookup-documentation-functions #'+llm-lookup-documentation-handler) + )) + + +(use-package! gptel-magit + :when (modulep! :tools magit) + :hook (magit-mode . gptel-magit-install)) + + +;; TODO: Aidermacs? diff --git a/modules/tools/llm/packages.el b/modules/tools/llm/packages.el new file mode 100644 index 000000000..6c6e681ae --- /dev/null +++ b/modules/tools/llm/packages.el @@ -0,0 +1,11 @@ +;; -*- no-byte-compile: t; -*- +;;; tools/llm/packages.el + +(package! gptel :pin "1aa5f1c10df34aeb08f677cd4aa4ef1fc12e87df") + +(package! gptel-quick + :recipe (:host github :repo "karthink/gptel-quick") + :pin "34acd437a7af8a387c14428bd1abdb3cd9e95d9d") + +(when (modulep! :tools magit) + (package! gptel-magit :pin "7f586943040bbb6885adafaf3e61fb5137c64558")) diff --git a/static/init.example.el b/static/init.example.el index 2ad02a569..8e60d5892 100644 --- a/static/init.example.el +++ b/static/init.example.el @@ -97,6 +97,7 @@ ;;ein ; tame Jupyter notebooks with emacs (eval +overlay) ; run code, run (also, repls) lookup ; navigate your code and its documentation + ;;llm ; when I said you needed friends, I didn't mean... ;;lsp ; M-x vscode magit ; a git porcelain for Emacs ;;make ; run make tasks from Emacs