Skip to content

An Interactive interface for "GitHub CLI" client inside GNU Emacs using Consult

License

Notifications You must be signed in to change notification settings

armindarvish/consult-gh

Repository files navigation

Consult-GH - A GitHub CLI client inside GNU Emacs using Consult

Armin Darvish GNU Emacs

**NOTICE**: Around Oct. 10th, 2023 there was a major update to use consult-async. This required reimplementing the package from scratch and may break old version. In the new version, there are many new features and functionalities inclduing:

  • async search, i.e. dynamic update of completion table as user enters an entry
  • dynamically add additional command line arguments in the minibuffer
  • search pull requests and codes
  • when searching codes, can open files and jump to the code in an emacs buffer
  • highlight relevant search terms, code snippets, etc. in preview buffers
  • transient menu to quickly find the desired interactive command or settings

You can learn about all the new functionalities below. If you prefer to use the old version, you can find it under the branch “v0.12” or in this release: release v0.12

About Consult-GH

Main Functions and Interactive Commands

Consult-GH provides an interface to interact with GitHub repositories (search, view files and issues, clone, fork, …) from inside Emacs. It uses the awesome package consult by Daniel Mendler and GitHub CLI and optionally Embark by Omar Antolín Camarena, and provides an intuitive UI using minibuffer completion familiar to Emacs users.

Consult-GH offers the following “MAIN” interactive commands

List Repos, Issues or PRs:

  1. consult-gh-repo-list: Finds repositories for a given GitHub user/organization, similar to running gh repo list in the command line.
  2. consult-gh-issue-list: Lists issues of a given GitHub repository, similar to running gh issue list in the command line.
  3. consult-gh-pr-list: Lists pull requests of a given GitHub repository, similar to running gh pr list in the command line.

Search Functions:

  1. consult-gh-search-repos: Search github repositories, similar to running gh search repos in the command line.
  2. consult-gh-search-issues: Search github issues, similar to running gh search issues in the command line.
  3. consult-gh-search-prs: Search github pull requests, similar to running gh search prs in the command line.
  4. consult-gh-search-code: Search for code on github, similar to running gh search code in the command line.

Browse File Contents:

  1. consult-gh-find-file: Find files within any branch of any repository.

Quickly See Repositories of Favorite Users/Organizations:

  1. consult-gh-default-repos: This calls consult-gh-repo-list on a defined default list of orgs stored in variable consult-gh-default-orgs-list for quick access to frequently used repositories. This can for example be useful for accessing your own repositories (in multiple accounts) quickly.

Clone or Fork Repos:

  1. consult-gh-repo-clone: Quickly clone a repository with just typing the name of the repository. This function has a post-hook consult-gh-repo-post-clone-hook that cna be used for example to switch o appropriate directory, etc.
  2. consult-gh-repo-fork: Quickly fork one or more repositories. This function also has a post-hook consult-gh-repo-post-fork-hook, that cna be used for example to clone the forked repository.

Furthermore, Consult-GH, also provides a number of useful Embark actions (see examples below.)

Why Use Consult-GH?

While there are several packages for interacting with GitHub and GitHub API such as gh.el, magit/ghub and magit/forge, git-link, browse-at-remote, and … in my opinion none of these packages provide an intuitive UI to interact with GitHub repositories. Some of these are a collection of low-level API calls without user-friendly interactive commands and others simply retrieve a URL in the browser instead of providing GitHub interface inside Emacs. As a result, the user either has to implement their own functions to use the API calls or simply jump to the browser to interact with GitHub. Consult-GH aims to fill this gap and provide a tool that allows the user to interact with GitHub from within Emacs.

Note that currently Consult-GH does not provide interactive commands to manage issues or pull request mainly because those functionalities are already available in other packages or tools. Personally, I like to use Consult-GH for searching repositories, browsing issues or view/download files without cloning entire repositories, etc. and use a package like magit/forge for managing issues, pull requests, etc. That said, I am open to including managing issues, pull requests or releases if there is a clear advantage in offering that as part of Consult-GH.

Getting Started

Installation

Before you start, make sure you understand that this is work in progress in its early stage and bugs and breaks are very much expected so use this at your own risk.

Requirements

In order to use Consult-GH, you need the following requirements:

To install GitHub CLI, follow the official documentations here: GitHub CLI Installation. Make sure you are logged in by running gh auth login and following the instructions. Refer to the official manual if you need further help, GitHub CLI Manual.

Why use gh instead of other Emacs packages? While there are other Emacs packages to interact with GitHub API, we use “gh” commandline tool as the backend instead of direct calls to REST API or GraphQL, and this is very much intentional. By leaving API functionalities to the official GitHub CLI tool, we simplify usage (no need to set up authentication within Emacs), reduce security risks (no risk of exposing authentication tokens, …) and increase maintainability (no need to keep compatibility with API changes).

To install consult follow the official instructions here: Configuration of Consult.

Also, make sure you review Consult’s README since it recommends some other packages and useful configurations for different settings. Some of those may improve your experience of Consult-GH as well. In particular the section about asynchronous search is important for learning how to use inputs to search for result and narrow down in minibuffer.

json library in Emacs

As of Emacs 27, json is available as built-in if Emacs is compiled with json. You can run the command json-available-p to see if it is available in your version of Emacs. If json is not available you may still be able to use Consult-GH with limited functionality (for example you cannot view file contents).

Recommended (but not required) packages

The following packages are not strictly required for Consult-GH to work, but it can improve your experience depending on your use-case.

Since gh returns information in markdown, installing markdown-mode can significantly improve your experience (e.g. readability of previews, etc.). When markdown-mode is available, by default Consult-GH will use it as major mode to show previews of READMEs, otherwise it will be in raw text in fundamental mode.

Installing Consult-GH Package

Consult-GH is not currently on ELPA or MELPA. Therefore, you need to install it using an alternative non-standard package managers such as straight.el or use manual installation.

straight.el

To install Consult-GH with straight.el you can use the following command. Make sure you load consult-gh after loading consult (e.g. =require consult=)

(straight-use-package
 '(consult-gh :type git :host github :repo "armindarvish/consult-gh" :branch "main"))

or if you use use-package macro with straight, you can do:

(use-package consult-gh
	:straight (consult-gh :type git :host github :repo "armindarvish/consult-gh"
        :after consult)
)

You can also fork this repository and use your own repo.

manual installation

Clone this repo and make sure the files are on your load path, as described on EmacsWiki.

Make sure you load consult (e.g. =require consult=) before you load consult-gh.

Configuration

Consult-GH is built with the idea that the user should be able to customize everything based on their use-case. In fact, the default configurations are minimal and prioritize performance over usability, therefore the user is very much expected to configure Consult-GH according to their use case. For example, with the default configuration, when selecting a repository, Consult-GH opens the link in a browser, but you can configure the package to show the README inside Emacs or do something else (e.g. clone the repository). Therefore, I recommend you read through this section and understand how to configure the package according to your needs and for your specific use-case, but if you just want a drop-in minimal config, look at the snippet below and make sure you set the consult-gh-default-orgs-list to your own GitHub username instead of “armindarvish”:

(use-package consult-gh
  :straight (consult-gh :type git :host github :repo "armindarvish/consult-gh")

  :config
  ;;add your main GitHub account (replace "armindarvish" with your user or org)
  (add-to-list 'consult-gh-default-orgs-list "armindarvish")

  ;;use "gh org list" to get a list of all your organizations and adds them to default list
  (setq consult-gh-default-orgs-list (append consult-gh-default-orgs-list (remove "" (split-string (or (consult-gh--command-to-string "org" "list") "") "\n"))))

  ;; set the default folder for cloning repositories, By default Consult-GH will confirm this before cloning
  (setq consult-gh-default-clone-directory "~/")
)

The configuration above adds “armindarvish” to the default orgs (used by consult-gh-default-repos so you can quickly see all your repositories.

Customization

The following customizable variables are provided:

consult-gh-tempdir

This is where temporary files are saved. By default, this is set to your system temporary directory (temporary-file-directory variable in Emacs). Consult-GH uses this folder to store temporary files (such as files you are previewing).

consult-gh--repo-maxnum

This is the limit passed to gh as --limit argument to gh repo list or gh search repos commands and defines the number of repos shown when listing or searching repos. By default, it is set to 30 following the default values of gh itself, but it can be customized by the user to see more or fewer results.

Note that, this is a global setting, but since the update to v2, the user can add additional command line arguments in the minibuffer, and therefore adding the command line argument (e.g. -- -L 100) in the minibuffer will dynamically override this setting. See Features and Demos for screenshots and examples.

consult-gh--issue-maxnum

This is the limit passed to gh as --limit argument to gh issue list or gh search issues commands and defines the number of issues shown when listing or searching for issues. By default, it is set to 30 following the default values of gh itself, but it can be customized by the user to see more or fewer results.

Similar to consult-gh–repo-maxnum, this can be overridden by passing command line arguments directly in the minibuffer (e.g. adding -- -L 100 in the minibuffer entry).

consult-gh--pr-maxnum

Similar to consult-gh–issue-maxnum but for pull requests.

consult-gh--code-maxnum

Similar to maxnum variables above but for codes (for example search results for code i.e. gh search code).

consult-gh-large-file-warning-threshold

This is the maximum file size, above which consult-gh requests a confirmation for previewing, opening or saving the file. Default value is set by emacs built-in large-file-warning-threshold variable, but since consult-gh is downloading files from the internet, you may want to set this to a smaller value than large-file-warning-threshold depending on your network performance.

consult-gh-prioritize-local-folder

This varibale defines whther gh uses the git repo in the local folder to select/guess the repository for commands like consult-gh-find-file and consult-gh-issue-list, etc. Note that everything is still retrieved from the remote (for example consult-gh-find-file would fetch the contents of the repo from remote and not from the local folder) but the local repo name is used instead of querying the user. You can set this varibale to =’suggest=, t, or nil

  • ‘suggest simply adds the local repo name as initial input in the minibuffer so you don’t have to type it out.
  • t would skip the query and uses the local repo name, if any, otherwise it falls back to querying the user.
  • nil would not suggest the local repo name as initial-input but instead uses it as default value. That means the local repo is added to the end of history list (accessible by default keybinding M-n).

consult-gh--issues-state-to-show

The state of issues shown when listing or searching for issues. This is the string passed as --state argument to gh search issues or gh issue list and can accept open, closed or all for open, closed or all issues, respectively.

Note that, this is a global setting, but since the update to v2, the user can add additional command line arguments in the minibuffer, and therefore adding the command line argument (e.g. -- --state closed) in the minibuffer will dynamically override this setting. See Features and Demos for screenshots and examples.

consult-gh--issues-state-to-show

Similar to consult-gh–issues-state-to-show but for pull requests. This is the string passed as --state argument to gh search prs or gh pr list and can accept open, merged, closed or all for open, merged, closed or all pull requests, respectively.

consult-gh-default-orgs-list

This is a list of default organizations you want to access frequently. I set this variable to organizations I am part of (a.k.a. to look at my own repositories) but you can add any account you want to look at frequently to this list. Here is an example of setting the default list to “alphapapa” and “systemcrafters”:

(setq consult-gh-default-orgs-list '("alphapapa" "systemcrafters"))

or if you want to append to the list:

(setq consult-gh-default-orgs-list (append consult-gh-default-orgs-list '("alphapapa" "systemcrafters")))

consult-gh-preview-buffer-mode

This is the major-mode used to show repository previews. By default, it is set to markdown-moe because gh repo view returns the README contents (commonly in markdown syntax). But if you prefer to see the contents in org-mode format, you can set this variable to =’org-mode=. Be aware that currently, the org-mode conversion is done with some simple regex replacements and while the performance is decent and the converted version is perfectly understandable, the org conversion may cause some inaccuracies. If you want to try this you can do:

(setq consult-gh-preview-buffer-mode 'org-mode)

consult-gh-show-preview

This variable is a boolean determining whether Consult-GH shows previews or not. By default, this is set to nil because loading repository views or file contents can be resource-heavy depending on the size of the content. Therefore, it is left to the user to intentionally turn this feature on if it is suitable for their use-case and their setup.

Note that getting previews makes an API call to GitHub and downloads contents of a file. When consult-gh-show-preview is set to nil (default setting), no API call is made (no resources used) and no preview will be available either. This might be a useful configuration if you only want to see the name of repositories or issues and do actions such as cloning, forking or getting links, or jumping to urls in the browser but not for viewing files or issues within Emacs.

If you want to be able to get a preview on demand without turning previews on globally, then look at =consult-gh-preview-key= below.

consult-gh-preview-key

This is similar to consult-preview-key but only for consult-gh. By default, it is set to the value of consult-preview-key to keep consistent experience across different consult packages, but you can set this variable explicitly for consult-gh. For example, if you have turned preview on by setting consult-gh-show-preview to t, but you still only want to see previews on demand, you can set consult-gh-preview-key to the key binding that shows the preview. Here is an example using M-o as preview key. With this setting, previews are shown only when you hit meta+o.

(setq consult-gh-show-preview t)
(setq consult-gh-preview-key "M-o")

Be aware that getting previews is resource heavy since it has to make an API call to GitHub and download contents of a file. If you set a specific key for consult-gh-preview-key, this API call and downloading the content is done only when you hit the key binding.

consult-gh-confirm-name-before-fork

This is a boolean determining whether Consult-GH asks for a repo name before forking a repository. By default, it is set to nil, meaning that Consult-GH uses the same repo name when forking.

consult-gh-confirm-before-clone

This is a boolean determining whether Consult-GH asks for path and directory name before cloning a repository. By default, it is set to t, meaning that Consult-GH asks the user for the path to clone a repository and the name to give the directory. However, if you don’t want consult-gh to ask you every time you clone a repository, you can set this variable to nil, in which case Consult-GH clones repositories at consult-gh-default-clone-directory (see below) with the default name of the repository itself. Note that setting this variable to nil along with setting consult-gh-default-clone-directory to a directory where you keep all your repositories, allows quick cloning of multiple repositories.

consult-gh-default-clone-directory

This variable points to the directory where repositories are cloned by default. In the default settings, this is set to =”~/”= (a.k.a. user’s home directory), and the user is asked for confirmation before cloning. Therefore, in the default setting no matter what this variable is, you can still choose the right path to clone each repository, but this means that you have to do this for every each repository you clone. By setting this variable to a default convenient path where you keep all your repositories, for example =”~/code/”= or =”~/projects/”= , you can minimize the effort to navigate to the right path. Keep in mind that if you do clone multiple repositories at the same time, it would be convenient to have this variable set to the right path, so you don’t have to navigate to it for each repository especially if you turn consult-gh-confirm-before-clone to nil (see above).

consult-gh-ask-for-path-before-save

This is a boolean determining whether Consult-GH asks for a path before saving a file (for single files and not cloning entire repositories). By default, it is set to t, meaning that Consult-GH asks the user for the path to save a file. However, if you don’t want consult-gh to ask you every time you save a file, you can set this variable to nil, in which case Consult-GH saves files at consult-gh-default-save-directory (see below) with the name of the file. Note that setting this variable to nil along with setting consult-gh-default-save-directory, allows quick saving of multiple files (possibly even from different repositories).

consult-gh-default-save-directory

This variable stores the default path where files are saved and by default is set to ~/Downloads. Keep in mind that This is used for saving individual files and not for cloning entire repositories, which uses consult-gh-default-clone-directory (see above).

consult-gh-default-branch-to-load

This variable is used for choosing a branch when viewing files within a repository. By default, it is set to =”ask”= meaning that Consult-GH will ask the user which branch to clone. If you set this to nil, then Consult-GH will load the HEAD of the git repository. If you set this to confirm, Consult-GH will ask you if you want to view the HEAD of the repository and if not will ask you to choose a branch. If you set this to any other string, then Consult-GH uses that string as the name of the branch and will try to load this branch. Be aware that setting this to a string is probably not a good idea since this will be used for any repository and if the branch does not exist, will cause an error.

consult-gh-repo-action

This variable stores the function that is called when a repository is selected. By default, it is bound to #'consult-gh--repo-browse-url-action which opens the homepage of the repository in a browser. You can change it to other provided functions such as #'consult-gh--repo-view-action which instead fetches the README of the repository within an Emacs buffer or #' consult-gh--repo-browse-files-action which shows the file tree of the repository (after choosing a branch). Other provided built-in actions include #'consult-gh--repo-clone-action and #'consult-gh--repo-fork-action. You can also set this variable to any custom function as long as it follows the patterns of the built-in functions (e.g. input ARGs,…)

consult-gh-issue-action

Similar to consult-gh-repo-action but for issues. This variable stores the default function that is called, when an issue is selected. By default, it is bound to #'consult-gh--issue-browse-url-action which opens the issue page in a browser. Alternatively, you can bind it to consult-gh--issue-view-action if you want to see the issue inside an Emacs buffer. Note that this is only for viewing issues and not interacting (adding posts, filing new issues, etc.) with them. This is mainly due to the fact that the gh backend itself is also limited when it comes to managing issues (interactive command line queries are not that useful!). In the future, I may add more features here, but keep in mind that for managing issues (and pull requests), we can use other packages like magit/forge. In fact, consult-gh now provides support for integration with magit/forge. You can use it by setting this variable to #'consult-gh-forge--issue-view-action provided in in ./consult-gh-forge.el (See below for more information).

consult-gh-pr-action

Similar to consult-gh-issue-action but for pull requests. This variable stores the default function that is called, when a pull request is selected; and by default, it is bound to #'consult-gh--pr-browse-url-action which opens the pull request page in a browser. Alternatively, you can bind it to consult-gh--pr-view-action if you want to see the issue inside an Emacs buffer. Alternatively, you can use magit/forge to view pull requests if you use #'consult-gh-forge--pr-view-action provided in ./consult-gh-forge.el (See below for more information).

consult-gh-code-action

Similar to other action variables above but for code snippets. This variable stores the default function that is called, when a code (search results from gh search code) is selected. By default, it is bound to #'consult-gh--code-browse-url-action which opens the url for the file containing the code snippet in a browser. Alternatively, you can bind it to consult-gh--code-view-action if you want to see the file inside an Emacs buffer. Note that when you open the file in an emacs buffer, consult-gh tries to put the cursor around the relevant code snippet in the file and highlights the snippet as well. (See below for screenshots and examples).

consult-gh-file-action

Similar to consult-gh-repo-action and consult-gh-issue-action but for files. This variable stores the default function that is called, when a file is selected. By default, it is bound to #' consult-gh--files-browse-url-action which opens the file page in a browser. Alternatively, you can bind it to other provided action functions for files such as consult-gh--files-view-action which opens the file in an Emacs buffer (in the right major mode as well) or consult-gh--files-save-file-action which allows you to save a file without cloning the entire repository. If you select multiple files, using =consult-gh-crm-separator=, you can even save multiple files possibly from different repositories.

consult-gh-highlight-matches

This variable determines if consult-gh highlights search terms, code snippets, etc. in minibuffer or preview buffers. By default it is set to t.

Example Customization for Good Performance and Functionality

Here is a good customization for great performance as well as functionality:

(use-package consult-gh
  :straight (consult-gh :type git :host github :repo "armindarvish/consult-gh")
  :custom
  (consult-gh-default-clone-directory "~/projects")
  (consult-gh-show-preview t)
  (consult-gh-preview-key "M-o")
  (consult-gh-repo-action #'consult-gh--repo-browse-files-action)
  (consult-gh-issue-action #'consult-gh--issue-view-action)
  (consult-gh-pr-action #'consult-gh--pr-view-action)
  (consult-gh-code-action #'consult-gh--code-view-action)
  (consult-gh-file-action #'consult-gh--files-view-action)
  (consult-gh-large-file-warning-threshold 2500000)
  (consult-gh-prioritize-local-folder 'suggest)
  :config
  ;;add your main GitHub account (replace "armindarvish" with your user or org)
  (add-to-list 'consult-gh-default-orgs-list "armindarvish")
  (require 'consult-gh-embark)

Features and Demos

For a detailed discussion and demo, see this blog post: consult-gh_working_with_github_inside_emacs_in_2023. If you prefer demo videos, you can watch this YouTube Playlist.

In the screenshots below, I am using vanilla emacs and a minimal config with modus-themes, vertico, marginalia, consult, and embark and this repo with the following config:

(use-package consult-gh
  :straight (consult-gh :type git :host github :repo "armindarvish/consult-gh")
  :custom
  (consult-gh-repo-maxnum 30) ;;set max number of repos to 30
  (consult-gh-issues-maxnum 100) ;;set max number of issues to 100
  (consult-gh-show-preview t) ;;show previews
  (consult-gh-preview-key "M-o") ;;show previews on demand by hitting "M-o"
  (consult-gh-preview-buffer-mode 'org-mode) ;;show previews in org-mode
  (consult-gh-repo-action #'consult-gh--repo-browse-files-action) ;;open file tree of repo on selection
  (consult-gh-issue-action #'consult-gh--issue-view-action) ;;open issues in an emacs buffer
  (consult-gh-pr-action #'consult-gh--pr-view-action) ;;open pull requests in an emacs buffer
  (consult-gh-code-action #'consult-gh--code-view-action) ;;open files that contain code snippet in an emacs buffer
  (consult-gh-file-action #'consult-gh--files-view-action) ;;open files in an emacs buffer
  :config
  (add-to-list 'consult-gh-default-orgs-list "armindarvish") ;;add your GitHub user
  (require 'consult-gh-embark)
  (add-to-list 'savehist-additional-variables 'consult-gh--known-orgs-list) ;;keep record of searched orgs
  (add-to-list 'savehist-additional-variables 'consult-gh--known-repos-list)) ;;keep record of searched repos

Search for Repositories

In the screenshot below, I use consult-gh-search-repos to search for repositories. The screenshot shows the updated capabilities with consult-async:

  • The results are dynamically updated when the entry is changed.
  • Command line arguments to gh can be added on demand from the minibuffer. For example entering magit -- -L 50 will change the max number of search results fetched to 50 or magit -- --sort forks sorts the repositories based on number of forks,…
  • Search keywords are highlighted inside minibuffer (a visual guide to see what matches the search term)
  • Search keywords are also highlighted inside preview buffers.
  • The results can be narrowed down by adding # after the search keyword and additional arguments. e.g. typing magit -- -L 70 --sort updated --order asc#forge in the minibuffer fetches repositories matching the keyword *”magit”* and sorts the results by the date that the repo was updated in the ascending order, then narrows the list to the ones that contain forge.
  • narrow down can be done based on info in the repo title but also marginalia info (e.g. visibility, update date, tags, …)

https://github.com/armindarvish/consult-gh/blob/screenshots/screenshots/consult-gh-search-repos.gif

Looking at Repositories of User(s)

In the screenshot below, I use consult-gh-repo-list to find repositories of a user/organization. I also show how to add command line arguments from the minibuffer. For example entering alphapapa -- --limit 200 --cource shows repositories belonging to “alphapapa” and limits the total number of results to 200, and then filters the results to only show the repositories that are a source (a.k.a. not a fork).

https://github.com/armindarvish/consult-gh/blob/screenshots/screenshots/consult-gh-repo-list.gif

Browsing Files in a Repository

In the screenshot below, I use consult-gh-find-file to browse files of a repository. The command first uses consult-gh-search-repos to get a repo, then asks the user to select a branch before showing a list of files in that repo and branch.

./screenshots/consult-gh-find-file.gif

Searching/Viewing Issues or Pull Requests

In the screenshot below, I use consult-gh-search-issues to search for issues and then view them inside Emacs. The screenshot shows the updated capabilities with consult-async:

  • The results are dynamically updated when the entry is changed.
  • Command line arguments to gh can be added on demand from the minibuffer. For example entering consult-gh -- --assignee=@me shows the search results for the keyword “consult-gh” and then filters the results to issues assigned to me. adding another command line argument to sort consult-gh -- --assignee=@me --sort created further sorts the issues by the date they were created.
  • Search keywords are highlighted inside minibuffer (a visual guide to see what matches the search term)
  • Search keywords are also highlighted inside preview buffers.

[[https://github.com/armindarvish/consult-gh/blob/screenshots/screenshots/consult-gh-search-issues.gif

Pull requests can be searched similary by using consult-gh-search-prs.

Searching for code

In the screenshot below, I use consult-gh-search-code to search for some code on github. For example I search for deque, then I add some command line arguments to limit the search to python files only (e.g. deque -- --language==python). When a preview is opened, consult-gh open the file containing the code and tries to find the region where the code is. This enables the user to interactively use the github code search, find relevant files and jump right to where the relevant code is used in the file.

https://github.com/armindarvish/consult-gh/blob/screenshots/screenshots/consult-gh-search-code.gif

Embark Integration

Consult-GH also provides embark integration defined in consult-gh-embark.el If you use Embark, you can use these commands for additional actions on items in consult-gh menu. For example, you can set your default action for repos bound to consult-gh-repo-browse-url-action which opens the repo’s url in a browser, but then call embark on any item for running alternative actions such as consult-gh-repo-clone or consult-gh-repo-fork etc. You can also call embark and select items with embark-select (by default bound to SPC) before running some commands on all of them, for example select multiple repos and run clone for all of them.

https://github.com/armindarvish/consult-gh/blob/screenshots/screenshots/consult-gh-embark.gif

Magit/Forge Integration

If you use forge to see issues of GitHub repositories, you can use the consult-gh-forge to directly open issues in a magit/forge buffer. In addition, you can edit issues in a forge buffer as you would normally do by forge-edit-post, forge-create-post, etc. Here it is in action:

https://github.com/armindarvish/consult-gh/blob/screenshots/screenshots/consult-gh-forge.gif

Set Up and Customization of Forge Integration

Warning: Before you decide to use consult-gh-forge, be aware that due the way magit/forge is implemented, it is deeply integrated with magit and its different components (like ghub) and everything is intended for a git repository with a .git folder path to work otherwise magit will show errors. As a result, I had to reimplement some of the functionalities in magit and forge, to ensure that consult-gh-forge works without those errors and also does not break magit or forge. But this is still highly experimental and you may experience bugs and issues with magit and forge if you decide to integrate =consult-gh= with magit/forge. Also, dependence on the magit/forge package may cuase maintainability issues down the road. So use this at your own risk.

To use consult-gh-forge, make sure that both magit and forge are installed and loaded before loading consult-gh and then add require 'consult-gh-forge to your config. An example of a minimal config:

(use-package consult-gh
  :straight (consult-gh :type git :host github :repo "armindarvish/consult-gh")
  :after forge
  :config
  (require 'consult-gh-embark)
  (require 'consult-gh-forge)
  (setq consult-gh-preview-key "M-o")
  (setq consult-gh-repo-action #'consult-gh--repo-browse-files-action)
  (setq consult-gh-file-action #'consult-gh--files-view-action)
  (setq consult-gh-issue-action #'consult-gh-forge--issue-view-action) ;;this enables opening issues in magit/forge buffer
  (setq consult-gh-forge-timeout-seconds 20) ;;maximum time inseconds for consult-gh to try opening issuers in forge, and then reverts back to opening in normal emacs buffer with consult-gh-issue--view.
)

Note that we are trying to keep consult-gh-forge edits of forge database transparent. Therefore a list of all the repositories that are added to forge-database is stored under the variable consult-gh-forge-added-repositories and interactive commands are provided to remove them from forge-databse either all at once (by using consult-gh-forge-remove-added-repositories) or by interactive selection through consult-gh-forge-remove-repository. This can still be done by forge-remove-repository as well, but consult-gh versions provide a transparent way to only remove the forge repositories added by consult-gh.

Keep in Mind: consult-gh adds temporary folders to consult-gh-tempdir in order to do magit/forge actions, and therefore you may face issues when those temporary folders are deleted on system restarts. In this case, you may want to use consult-gh-forge-remove-added-repositories to clean up forge-database and then you should be able to use consult-gh-forge--issue-view normally again.

With consult-gh-forge, you get one more “customization” variable as well:

consult-gh-forge-timeout-seconds

This variable sets the maximum time in seconds that consult-gh-forge tries to load an issue in forge buffer, and if for some reason, it cannot do so, it reverts back to using consult-gh-issue--view= function that opens the issue in a normal emacs buffer. This provides a fail safe mechanism in case there are issues with magit/forge. By default, it is set to 10 seconds, which should be sufficient for most issues to load but this depends on your network performance and the size of the content that needs to be downloaded. Some issues especially the ones with many comments and posts can take longer to load depending on your network performance. If you experience this often, you may want to consider adjusting this variable to even longer times. On the other hand, if there is an issue with magit/forge, consult-gh would not try to open the issue in a normal buffer before the reaching the timeout time!

Transient Menu

After the major update on October 2023, consult-gh now has a transient menu. It can be accessed by running M-x consult-gh after loading consult-gh-transient module. Just make sure that the transient package is installed before loading consult-gh-transient.

(use-package consult-gh
  :straight (consult-gh :type git :host github :repo "armindarvish/consult-gh")
  :after forge transient
  :config
  (require 'consult-gh-embark)
  (require 'consult-gh-transient)
)

https://github.com/armindarvish/consult-gh/blob/screenshots/screenshots/consult-gh-transient.gif

Bug reports

To report bug, first check if it is already reported in the *issue tracker* and see if there is an existing solution or add relevant comments and discussion under the same issue. If not file a new issue following these steps:

  1. Make sure the dependencies are installed, and you are logged in by running gh auth login in the terminal.
  2. Make sure that dependencies (i.e. consult and gh) work properly independent of Consult-GH. You can for example run some other consult commands (e.g. consult-buffer) to make sure the problem is not form consult and run some gh commands in the shell (i.e. gh repo list) to see if they are working properly. If the problem is from consult or gh, please refer to their manuals and documentation.
  3. Remove the package and install the latest version (along with dependencies) and see if the issue persists.
  4. In a bare bone vanilla Emacs (>=28) (e.g. emacs -Q), install the latest version of Consult-GH (and its dependencies) without any configuration or other packages and see if the issue still persists.
  5. File an issue and provide important information and context in as much detail as possible in your bug report. Important information can include:
  • Your operating system, version of Emacs (or the version of emacsen you are using), version of gh (run gh --version in a shell), version of consult (see pkg-info).
  • The installation method and the configuration you are using with your Consult-GH.
  • If there is an error message, turn debug-on-error on (by M-x toggle-debug-on-error) and include the backtrace content in your report.
  • If the error only exists when you have some other packages installed, list those packages (e.g. problem happens when evil is installed)

Contributions

This is an open source package, and I appreciate feedback, suggestions, ideas, etc.

If you want to contribute to the code, please note that the main branch is currently stable (as stable as a work in progress like this can be) and the develop branch is the current work in progress. So, start from the develop branch to get the latest work-in-progress updates and create a new branch with names such as feature/name-of-the-feature or fix/issue, … Do the edits and then create a new pull request to merge back with the develop branch when you are done with your edits. Importantly, keep in mind that I am using a literate programming approach (given that this is a small project with very limited number of files) where everything goes into consult-gh.org and then gets tangled to appropriate files (for now that includes consult-gh.el and consult-gh-embark.el). If you open a pull-request where you directly edited the .el files, I will likely not approve it because that will then get overwritten later when I tangle from the .org file. In other words, Do Not Edit The .el Files! only edit the .org file and tangle to .el files.

Acknowledgments

Obviously this package would not have been possible without the fabulous Consult package. It also took inspiration from other packages related to consult as well as gh.el, magit/forge and some other GitHub related work. Special thanks to the maintainer of consult package, Daniel Mendler, for useful advice, feedback and discussion.