Skip to content
Switch branches/tags
Go to file
Cannot retrieve contributors at this time


Doom Emacs is an active and ongoing project, maintained mostly by a single person, but includes the efforts of 200 contributors and growing. There is no shortage of things that need doing; bugs that need stomping, features that need implementing, and documentation that needs documenting. If Doom’s been useful to you, convert some caffiene into code; it’d be a huge help!

You are welcome to join us on our Discord server, otherwise read on to learn how to contribute to our fine corner of the interwebs.

Table of Contents

Where can I help?

  • Our issue tracker has many issues. If you find one that you have an answer to, it would be a huge help!
  • Look for issues tagged good first issue. These were judged to have a low barrier of entry.
  • Look for issues tagged help wanted. These tend to be a little (or a lot) harder, and are issues outside my own expertise.
  • If you’ve encountered a bug, file a bug report.
  • The development roadmap board is a rough timeline of what is being worked on and when. It will give you an idea of what will change and where you can redirect your efforts.
  • The plugins under review board lists third party plugins being considered (or rejected) for inclusion in Doom Emacs. Approved and unclaimed packages are open for you to implement yourself.
  • The upstream bugs board lists known issues that have external causes, but affect Doom. If you’re feeling adventurous (or are better acquainted with the cause) perhaps you can address them at the source.

Reporting issues

You’ve found a problem and you’re ready to fire off that bug report. Hold up! Before you do that, have a look at our Troubleshooting guide. If none of these suggestions pan out, then it is time to file a bug report.

An effective bug report is informative. Please try to provide:

  • A backtrace of all mentioned errors.
  • A step-by-step reproduction of the issue.
  • Information about your Doom config and system environment.
  • Screenshots/casts of the issue (if possible).

This section will show you how to collect this information.

Acquire a backtrace from errors

See ”How to extract a backtrace from an error” in the Getting Started guide.

Create a step-by-step reproduction guide

Include information about your Doom install

Debugging crashes with gdb

Suggesting features, keybinds and/or enhancements

Contributing code

There’s much to be done around here! We need bugfixes, new features, and documentation. If you’d like to convert some caffeine into Emacs Lisp, here are a few considerations before starting that PR:


Code style

Doom conforms to @bbatsov’s emacs-lisp style guide with the following exceptions:

  • Use mapc instead of seq-do.
  • No hanging parentheses
  • We use DEPRECATED to indicate code that will eventually be removed.

Naming conventions

Doom has a number of naming conventions that it uses in addition to the standard lisp conventions. Third party packages may use their own conventions as well.

Lisp Naming Conventions

The lisp conventions are simple. Symbols follow NAMESPACE-SYMBOLNAME for public variables/functions (e.g. bookmark-default-file or electric-indent-mode) and NAMESPACE--SYMBOLNAME for private ones (e.g. byte-compile--lexical-environment and yas--tables).

NAMESPACE is usually the name of the containing file or package. E.g. the company plugin prefixes all its variables/functions with company-.

Doom Naming Conventions

Denotes a public command designed to be used interactively, via M-x or a keybinding. e.g. doom/info, +popup/other, +ivy/rg.
A public evil operator, motion or command. e.g. +evil:align, +ivy:rg.
doom-[-]NAME-h or +MODULE-[-]NAME-h
A non-interactive function meant to be used (exclusively) as a hook. e.g. +cc-fontify-constants-h, +flycheck-buffer-h.
doom-[-]NAME-a or +MODULE-[-]NAME-a
Functions designed to be used as advice for other functions. e.g. doom-set-jump-a, doom--fix-broken-smie-modes-a, +org--babel-lazy-load-library-a
doom-[-]NAME-fn or +MODULE-[-]NAME-fn
Indicates an strategy function. A good rule of thumb for what makes a strategy function is: is it interchangeable? Can it be replaced with another function with a matching signature? e.g. +lookup-dumb-jump-backend-fn, +magit-display-buffer-fn, +workspaces-set-project-action-fn
A public Doom “autodef” function or macro. An autodef should always be defined, even if its containing module is disabled (i.e. they will not throw a void-function error). The purpose of this is to avoid peppering module configs with conditionals or `after!` blocks before using their APIs. They should noop if their module is disabled, and should be zero-cost in the case their module is disabled.

Autodefs usually serve to configure Doom or a module. e.g. after!, set-company-backends!, set-evil-initial-state!

Commits & PRs

  • Target the correct branch:
    • rewrite-docs for changes to *.org files.
    • master for everything else.
    • Never develop. It’s EOL.
  • Consult our do-not-PR list for things we won’t accept pull requests for.

Keybind conventions

Your first code contribution

Submitting pull requests

Contributing to Doom core

Contributing to an existing module

Contributing a new module

Contributing documentation

Doom Emacs’ documentation is an ongoing effort. If you have suggestions, improvements, tutorials and/or articles to submit, don’t hesitate to get in contact via our Discord server or email. I appreciate any help I can get!

Contributing to Doom’s manual

Contributing module documentation

Help keep packages up-to-date!

Doom pins all its packages to reduce the likelihood of upstream breakage leaking into Doom Emacs. However, we may miss when a package releases hotfixes for critical issues. Let us know or PR a bump to our pinned packages.

Other ways to support Doom Emacs

Special thanks