Copilot.el is an Emacs plugin for GitHub Copilot.
Warning: This plugin is unofficial and based on binaries provided by copilot.vim.
Note: You need access to GitHub Copilot to use this plugin.
-
Install Node.js (only support 12.x to 17.x, limited by upstream). Workaround for node.js v18+ users: install an old version of node.js via nvm and set
copilot-node-executable
to it. -
Setup
copilot.el
as described in the next section. -
Login to Copilot by
M-x copilot-login
. You can also check the status byM-x copilot-diagnose
. -
Enjoy!
Add package definition to ~/.doom.d/packages.el
:
(package! copilot
:recipe (:host github :repo "zerolfx/copilot.el" :files ("*.el" "dist")))
Configure copilot in ~/.doom.d/config.el
:
;; accept completion from copilot and fallback to company
(defun my-tab ()
(interactive)
(or (copilot-accept-completion)
(company-indent-or-complete-common nil)))
(use-package! copilot
:hook (prog-mode . copilot-mode)
:bind (("C-TAB" . 'copilot-accept-completion-by-word)
("C-<tab>" . 'copilot-accept-completion-by-word)
:map company-active-map
("<tab>" . 'my-tab)
("TAB" . 'my-tab)
:map company-mode-map
("<tab>" . 'my-tab)
("TAB" . 'my-tab)))
Strongly recommend to enable childframe
option in company
module ((company +childframe)
) to prevent overlay conflict.
Edit your ~/.spacemacs
:
;; ===================
;; dotspacemacs/layers
;; ===================
;; add copilot.el to additional packages
dotspacemacs-additional-packages
'((copilot :location (recipe
:fetcher github
:repo "zerolfx/copilot.el"
:files ("*.el" "dist"))))
;; ========================
;; dotspacemacs/user-config
;; ========================
;; accept completion from copilot and fallback to company
(defun my-tab ()
(interactive)
(or (copilot-accept-completion)
(company-indent-or-complete-common nil)))
(with-eval-after-load 'company
;; disable inline previews
(delq 'company-preview-if-just-one-frontend company-frontends)
;; enable tab completion
(define-key company-mode-map (kbd "<tab>") 'my-tab)
(define-key company-mode-map (kbd "TAB") 'my-tab)
(define-key company-active-map (kbd "<tab>") 'my-tab)
(define-key company-active-map (kbd "TAB") 'my-tab))
(add-hook 'prog-mode-hook 'copilot-mode)
(define-key evil-insert-state-map (kbd "C-<tab>") 'copilot-accept-completion-by-word)
(define-key evil-insert-state-map (kbd "C-TAB") 'copilot-accept-completion-by-word)
(use-package copilot
:straight (:host github :repo "zerolfx/copilot.el" :files ("dist" "*.el"))
:ensure t)
;; you can utilize :map :hook and :config to customize copilot
Please make sure you have these dependencies installed, and use load-file
or load-path
+ require
to load it.
dash
s
editorconfig
(add-hook 'prog-mode-hook 'copilot-mode)
To customize the behavior of copilot-mode
, please check copilot-enable-predicates
and copilot-disable-predicates
.
You need to bind copilot-complete
to some key and call copilot-clear-overlay
inside post-command-hook
.
In general, you need to bind copilot-accept-completion
to some key in order to accept the completion. Also, you may find copilot-accept-completion-by-word
is useful.
; complete by copilot first, then company-mode
(defun my-tab ()
(interactive)
(or (copilot-accept-completion)
(company-indent-or-complete-common nil)))
; modify company-mode behaviors
(with-eval-after-load 'company
;; disable inline previews
(delq 'company-preview-if-just-one-frontend company-frontends)
(define-key company-mode-map (kbd "<tab>") 'my-tab)
(define-key company-mode-map (kbd "TAB") 'my-tab)
(define-key company-active-map (kbd "<tab>") 'my-tab)
(define-key company-active-map (kbd "TAB") 'my-tab))
; complete by copilot first, then auto-complete
(defun my-tab ()
(interactive)
(or (copilot-accept-completion)
(ac-expand nil)))
(with-eval-after-load 'auto-complete
; disable inline preview
(setq ac-disable-inline t)
; show menu if have only one candidate
(setq ac-candidate-menu-min 0)
(define-key ac-completing-map (kbd "TAB") 'my-tab)
(define-key ac-completing-map (kbd "<tab>") 'my-tab))
(define-key global-map [remap indent-for-tab-command] '(lambda ()
(interactive)
(or (copilot-accept-completion)
(indent-for-tab-command))))
This is useful if you don't want to depend on a particular completion framework.
(defun my/copilot-tab ()
(interactive)
(or (copilot-accept-completion)
(indent-for-tab-command)))
(with-eval-after-load 'copilot
(define-key copilot-mode-map (kbd "<tab>") #'my/copilot-tab))
Or with evil-mode:
(with-eval-after-load 'copilot
(evil-define-key 'insert copilot-mode-map
(kbd "<tab>") #'my/copilot-tab))
Check the current status of the plugin. Also you can check logs in the *copilot events*
buffer and stderr output in the *copilot stderr*
buffer.
Login to GitHub, required for using the plugin.
Enable/disable copilot mode.
Try to complete at the current point.
Accept the current completion.
Clear copilot overlay in the current buffer.
Similar to copilot-accept-completion
, but accept the completion by line or word. You can use prefix argument to specify the number of lines or words to accept.
Cycle through the completion list.
Logout from GitHub.
The executable path of Node.js.
Time in seconds to wait before starting completion (default to 0). Note Copilot itself has a ~100ms delay because of network communication.
A list of predicate functions with no argument to enable Copilot in copilot-mode
. Copilot will be enabled only if all predicates return t
.
A list of predicate functions with no argument to disable Copilot in copilot-mode
. Copilot will be disabled if any predicate returns t
.
This is an example of using together with default frontend of company-mode
. Because both company-mode
and copilot.el
use overlay to show completion, so the conflict is inevitable.
To solve the problem, I recommend you to use company-box
(only available on GUI), which is based on child frame rather than overlay.
After using company-box
, you have:
In other editors (e.g. VS Code
, PyCharm
), completions from copilot and other sources can not show at the same time.
But I decided to allow them to coexist, allowing you to choose a better one at any time.
- If you are using
whitespace-mode
, make sure to removenewline-mark
fromwhitespace-style
.
- Make sure you have restarted your Emacs (and rebuild the plugin if necessary) after updating the plugin.
- Please paste related logs in the
*copilot events*
and*copilot stderr*
buffer. - If an exception is thrown, please also paste the stack trace (use
M-x toggle-debug-on-error
to enable stack trace).
- Setup Copilot without Neovim
- Cycle through suggestions
- Add Copilot minor-mode
-
Add package to MELPA
These projects helped me a lot: