#+TITLE: forge-llm #+AUTHOR: Roger Gonzalez #+EMAIL: roger@rogs.me [[https://melpa.org/#/forge-llm][file:https://melpa.org/packages/forge-llm-badge.svg]] [[https://git.rogs.me/rogs/forge-llm/actions/workflows/ci.yml/badge.svg]] * forge-llm :PROPERTIES: :ID: 81db1fd1-a5db-4201-9113-72889f7c7829 :END: Generate Pull Request descriptions for Forge using LLM providers through the [[https://github.com/ahyatt/llm][llm]] package. [[https://gitlab.com/uploads/-/system/project/avatar/67959042/logo.png]] ** Overview :PROPERTIES: :ID: e5e5a1d0-cf5a-4f45-8d4c-f2f75339bf9a :END: ~forge-llm~ is an Emacs package that integrates Large Language Models (LLMs) with Forge, a Magit interface to GitHub and GitLab forges. This package helps you generate high-quality Pull Request descriptions based on your git diff and repository PR templates. Main features: - Automatically finds and uses your repository's PR template - Generates PR descriptions based on git diffs between branches - Seamless integration with Forge's PR creation workflow - Supports any LLM provider supported by the ~llm~ package - Stream LLM responses in real-time ** Dependencies :PROPERTIES: :ID: f30fedc1-a24a-4308-bc78-6f9c01857c18 :END: - [[https://magit.vc/][Magit]] and [[https://github.com/magit/forge][Forge]] (*Note:* ~forge~ is essential for this package to operate) - [[https://github.com/ahyatt/llm][llm]] - Emacs 25.1+ ** Installation :PROPERTIES: :ID: a4cfca4c-6029-445a-9e1d-88293ddaaff7 :END: *** Using MELPA (Recommended) :PROPERTIES: :ID: 0e561e53-10f6-4a0b-90e3-46094124aeb2 :END: The easiest way to install ~forge-llm~ is via MELPA. Ensure you have MELPA configured in your Emacs setup (it's included by default in many distributions like Doom Emacs and Spacemacs). #+begin_src emacs-lisp (use-package forge-llm :ensure t :after forge :config (forge-llm-setup)) #+end_src *** Using straight.el with use-package :PROPERTIES: :ID: 0c4a74cd-f752-4b3f-a729-0cc5a34f3d38 :END: If you use ~straight.el~ to manage your packages, it can install ~forge-llm~ directly from MELPA. Ensure MELPA is included in your ~straight-recipe-repositories~ or ~straight-recipe-sources~. #+begin_src emacs-lisp (use-package forge-llm ;; straight.el will fetch this from MELPA if :ensure t is used ;; and straight.el is configured as the handler for use-package. :ensure t :after forge :config (forge-llm-setup)) #+end_src *** Using Doom Emacs :PROPERTIES: :ID: 6c2a34d5-8e1a-4f7e-9c2b-1d9e7b8f3a1d :END: **** Basic Setup :PROPERTIES: :ID: f7a2b3c4-d5e6-4f7a-8b9c-0d1e2f3a4b5c :END: 1. Add the following to your ~packages.el~ (ensure MELPA is enabled in your Doom configuration, which is usually the default): #+begin_src emacs-lisp (package! forge-llm) (package! llm) ; Dependency #+end_src 2. Add somewhere in your ~config.el~: #+begin_src emacs-lisp ;; Load and setup forge-llm after forge is loaded (after! forge (require 'forge-llm) (forge-llm-setup)) ;; Configure your LLM provider (example using OpenAI) ;; Place this somewhere appropriate in your config.el (require 'llm-openai) ; Or your preferred LLM provider (setq forge-llm-llm-provider (make-llm-openai :key "YOUR-OPENAI-KEY")) ; Replace with your key/provider setup #+end_src 3. Run ~doom sync~ to install the package. **** Keybindings :PROPERTIES: :ID: 3e4f5a6b-7c8d-9e0f-1a2b-3c4d5e6f7a8b :END: The package automatically sets up Doom Emacs keybindings when Doom is detected: - ~SPC m g~ - Generate PR description in a separate buffer - ~SPC m p~ - Generate PR description at point - ~SPC m t~ - Insert PR template at point No additional configuration is needed for these keybindings to work. *** Manual installation :PROPERTIES: :ID: b91cfecf-04a3-43c8-96d3-dea082e5ed6e :END: Clone the repository: #+begin_src shell git clone https://gitlab.com/rogs/forge-llm.git ~/.emacs.d/site-lisp/forge-llm #+end_src Add to your Emacs configuration: #+begin_src emacs-lisp (add-to-list 'load-path "~/.emacs.d/site-lisp/forge-llm") (require 'forge-llm) (forge-llm-setup) #+end_src ** Setting up LLM providers :PROPERTIES: :ID: 842282e1-4760-4687-96a1-4c15adb9a13d :END: ~forge-llm~ depends on the [[https://github.com/ahyatt/llm][llm]] package for LLM integration. You'll need to set up at least one LLM provider. Please refer to the [[https://github.com/ahyatt/llm?tab=readme-ov-file#setting-up-providers][llm documentation]] for detailed instructions. Some of the providers supported by the ~llm~ package include: - OpenAI - Anthropic (Claude) - Google (Gemini, Vertex AI) - Azure OpenAI - GitHub Models - Ollama (for local models like Llama, Mistral, etc.) - GPT4All (for local models) - llama.cpp (via OpenAI compatible endpoint) - Deepseek - Generic OpenAI-compatible endpoints See the [[https://github.com/ahyatt/llm?tab=readme-ov-file#setting-up-providers][llm documentation]] for the complete list and specific setup steps. *** Example: OpenAI provider :PROPERTIES: :ID: 108c5560-65ad-49e1-8c02-d4c0493bb2b2 :END: First, create an [[https://platform.openai.com/account/api-keys][OpenAI API key]]. Then configure the ~llm~ OpenAI provider: #+begin_src emacs-lisp (require 'llm-openai) (setq forge-llm-llm-provider (make-llm-openai :key "YOUR-OPENAI-KEY")) #+end_src *** Example: Anthropic provider :PROPERTIES: :ID: b9728ac5-f5c0-4d6b-8d3e-a4b7c3d9e1f0 :END: To use Claude models from Anthropic: #+begin_src emacs-lisp (require 'llm-claude) (setq forge-llm-llm-provider (make-llm-claude :key "YOUR-ANTHROPIC-KEY" :chat-model "claude-3-7-sonnet-20250219")) #+end_src *** Using auth-source for API keys (recommended) :PROPERTIES: :ID: 59f84b84-ce44-4208-8531-56992cae847e :END: For better security, use Emacs ~auth-source~ to store your API keys: #+begin_src emacs-lisp (use-package llm :ensure t :config (setq llm-warn-on-nonfree nil)) (require 'llm-openai) (use-package forge-llm :ensure t :after (forge llm) :custom (forge-llm-llm-provider (make-llm-openai :key (auth-source-pick-first-password :host "api.openai.com" :user "apikey"))) :config (forge-llm-setup)) #+end_src Content of ~.authinfo~ or ~.authinfo.gpg~: #+begin_src machine api.openai.com login apikey password YOUR-API-KEY-HERE #+end_src ** Usage :PROPERTIES: :ID: e6753914-01ee-41e9-bcdf-f3d6e75ee451 :END: After setting up ~forge-llm~, the following commands will be available *specifically within Forge's pull request creation buffer* (which runs in ~forge-post-mode~): | Key binding | Command | Description | |------------------------+--------------------------------------------+-------------------------------------------------------| | C-c C-l g | forge-llm-generate-pr-description | Generate a PR description (output to separate buffer) | | C-c C-l p | forge-llm-generate-pr-description-at-point | Generate a PR description at the current point | | C-c C-l t | forge-llm-insert-template-at-point | Insert the PR template at the current point | | SPC m g (Doom Emacs) | forge-llm-generate-pr-description | Generate a PR description (output to separate buffer) | | SPC m p (Doom Emacs) | forge-llm-generate-pr-description-at-point | Generate a PR description at the current point | | SPC m t (Doom Emacs) | forge-llm-insert-template-at-point | Insert the PR template at the current point | *** Demo: Generate PR description in a new buffer :PROPERTIES: :ID: 8d7e1f6a-3b2c-4a9e-8d7e-1f6a3b2c4a9e :END: Pressing ~C-c C-l g~ will generate a PR description and display it in a separate buffer: [[https://gitlab.com/-/project/67959042/uploads/3eed67e0b188d040906d30b6b6cc3ec6/generate-pr-desc.gif][file:https://gitlab.com/-/project/67959042/uploads/3eed67e0b188d040906d30b6b6cc3ec6/generate-pr-desc.gif]] /Click the image to view in full screen/ *** Demo: Generate PR description at point :PROPERTIES: :ID: 9e5d4f8b-4eab-8798-9e5d-4f8b4eab8798 :END: Pressing ~C-c C-l p~ will generate a PR description and insert it directly at the cursor position: [[https://gitlab.com/-/project/67959042/uploads/9e5d4f8b4eab87989eafca9f58baa467/generate-pr-at-point.gif][file:https://gitlab.com/-/project/67959042/uploads/9e5d4f8b4eab87989eafca9f58baa467/generate-pr-at-point.gif]] /Click the image to view in full screen/ *** Workflow: :PROPERTIES: :ID: d745d788-793a-4847-95d7-4f5105bc654d :END: 1. Create a PR using Forge as normal (~forge-create-pullreq~) 2. In the PR creation buffer, position your cursor where you want to insert the PR description 3. Press ~C-c C-l p~ to generate and insert a PR description based on your changes 4. Edit the description as needed and submit the PR *** Canceling Generation: :PROPERTIES: :ID: 7ddfeaab-31a3-4476-b770-7c9751566d88 :END: If you need to cancel an in-progress LLM request: - ~M-x forge-llm-cancel-request~ ** Customization :PROPERTIES: :ID: baff250b-65a2-48cf-ace8-af38996bd865 :END: You can customize various aspects of ~forge-llm~ through the following variables: *** PR Template Configuration :PROPERTIES: :ID: ccb75625-c64d-47ad-adbe-77862b4ebbb5 :END: - ~forge-llm-pr-template-paths~ - List of possible paths for PR/MR templates relative to repo root #+begin_src emacs-lisp (setq forge-llm-pr-template-paths '(".github/PULL_REQUEST_TEMPLATE.md" ".github/pull_request_template.md" "docs/pull_request_template.md" ".gitlab/merge_request_templates/default.md")) #+end_src - ~forge-llm-default-pr-template~ - Default PR template to use when no template is found in the repository *** LLM Provider Configuration :PROPERTIES: :ID: 8c3c77fb-a6ae-47bb-8c2b-2b82c2364d81 :END: - ~forge-llm-llm-provider~ - LLM provider to use. Can be a provider object or a function that returns a provider object (See the [[https://github.com/ahyatt/llm][llm package]] documentation for how to create provider objects). #+begin_src emacs-lisp (setq forge-llm-llm-provider (make-llm-openai :key "YOUR-API-KEY")) #+end_src - ~forge-llm-temperature~ - Temperature for LLM responses (nil for provider default) #+begin_src emacs-lisp (setq forge-llm-temperature 0.7) #+end_src - ~forge-llm-max-tokens~ - Maximum number of tokens for LLM responses (nil for provider default) #+begin_src emacs-lisp (setq forge-llm-max-tokens 1024) #+end_src - ~forge-llm-max-diff-size~ - Maximum size in characters for git diffs sent to the LLM (nil for no truncation) #+begin_src emacs-lisp ;; Default is 50000, set to nil to disable truncation (setq forge-llm-max-diff-size 100000) ; Increase to 100K characters ;; Or disable truncation completely (setq forge-llm-max-diff-size nil) #+end_src *** Prompt Configuration :PROPERTIES: :ID: f0cb4a2b-d919-4fe0-b286-317b93084174 :END: - ~forge-llm-pr-description-prompt~ - Prompt used to generate a PR description with the LLM. This prompt is formatted with the PR template and git diff. You can customize this prompt to match your project's PR description style: #+begin_src emacs-lisp (setq forge-llm-pr-description-prompt "Generate a PR description for the following changes. PR template: %s Git diff: ``` %s ``` Please generate a PR description that follows our team's style.") #+end_src ** Troubleshooting :PROPERTIES: :ID: 30489ac7-98ed-4820-a780-83c239e427f6 :END: - If you're having issues with the LLM provider, you can enable debug logging for ~llm~ by setting ~llm-log~ to ~t~. - Check the ~*forge-llm-debug-prompt*~ buffer to see the exact prompt being sent to the LLM. - Check the ~*forge-llm-output*~ buffer to see the raw output from the LLM. *** Common Issues: :PROPERTIES: :ID: 4b2fd630-290e-4a95-8315-e8db4b6f4217 :END: - *Error: "No LLM provider configured"* - Make sure you've set ~forge-llm-llm-provider~ to a valid provider object. - Ensure your API key is correct. - *Error: "Failed to generate git diff"* - Ensure you're in a repository with valid head and base branches. - Check if the current directory is within a git repository. - *PR Generation is too slow* - Consider using a faster model (like GPT-3.5-turbo instead of GPT-4). - Reduce ~forge-llm-max-tokens~ to limit the response size. - *PR template not found* - Check if your PR template is in one of the paths listed in ~forge-llm-pr-template-paths~. - Add your custom template path if needed. ** TO-DO: :PROPERTIES: :ID: 97dad50e-0d25-42aa-9fe6-5e6402256454 :END: - Add more examples and use cases ** Contributing :PROPERTIES: :ID: 398ecc9e-30c2-4af4-afc5-c793ab3bedaa :END: Contributions are welcome! Please feel free to submit a Merge Request. *** Development Setup :PROPERTIES: :ID: 237ac5d2-d323-4b7d-9c51-54760a3ccc53 :END: 1. Clone the repository: #+begin_src shell git clone https://gitlab.com/rogs/forge-llm.git cd forge-llm #+end_src 2. Install dependencies for development: - Ensure you have forge and llm packages ** Acknowledgments :PROPERTIES: :ID: b5d4c3e2-f1a0-4b9c-8d7e-6f5a4b3c2d1e :END: This project was heavily inspired by [[https://github.com/douo/magit-gptcommit][magit-gptcommit]]. Check it out! This package works very well with forge-llm. Another huge inspiration was [[https://github.com/xenodium][xenodium]], with their Emacs package [[https://github.com/xenodium/chatgpt-shell][chatgpt-shell]]. ** License :PROPERTIES: :ID: 14189649-a22f-4cf8-9850-9a8bb62456d3 :END: This project is licensed under the GNU General Public License version 3 - see the LICENSE file for details.