Skip to content

Contributor's guide#

Getting started#

Huge code bases can be intimidating and it always takes some time to get familiar with a project. Don't be afraid to ask questions and to say your opinion. We want to encourage you to share your thoughts with us, so if you have an idea for a new feature or how we can improve the existing ones, feel free to open an issue.

You should start by reading our docs. This also allows you to start contributing by improving our docs. Since documentation is very important to get new contibutors on board, this helps us to grow the community.

This document is only supposed as an introduction but we will add more doc files that contain detailed information on important parts of the project. Advanced features like webrender or javascript support are documented separately.


Most of the additional functionality of emacs-ng are in rust_src/. This is the root of the main crate, however the actual code is in rust_src/crates/, except the crates that are only used for the build.

Some crates will only built if you activate the related features when calling ./configure. You can find the features that are used by emacs-ng in Some of them on by default. Take a look at to see how they are activated during the build process.

We only apply changes to the emacs code if it's necessary for features that are defined in rust. This way there are less merge conflicts when we perform upstream merges.

Bug fixes that also affect emacs can be tracked by an issue, but should but fixed upstream.


We use bindgen to generate rust bindings for the functions defined in C. Those bindings are in the crate emacs and are used by other crates through importing them from the emacs crate.

The crate codegen holds the code that is responsible for generating the bindings.

There's an ongoing effort to explain how emacs-ng is built on top of emacs in handbook/


Since we use github actions, the ci related files are located at .github/workflow. The main job(test.yml) is for building emacs-ng on Linux and osx (including formatting with rustfmt). There's also docs.yml that is responsible for generating and deploying our docs. The remaining files are used to test if the nix build works and to create the release build that runs once a week.


Currently we only run some JavaScript related tests. Because there are several failing native lisp tests, we haven't included them in our build. However there's an open issue that tracks the status. At this point there are no tests that are written in rust.

If you want to know how you can run tests, look at handbook/ The file also contains some test examples.


The emacs crate also contains most of the code that allows us to make use of elisp types. One of the most important types is LispObject which is the equivalent to the C type Lisp_Object(handbook/

In order to define lisp functions in rust you have to take a look at the macro lisp_fn. Compared to the C version DEFUN it provides a lot more flexibility(handbook/

Adding features#

The rust ecosystem provides tons of possibilities to improve emacs. We intend to use make use of libgit through git2-rs to improve magit. It would also be cool if we would have a terminal emulator based on rust.

If you have any idea for a new feature you want to work on, just add a configure option and create a new crate. Do not hesitate to ask for help.

Logs and debugging#

If you configure with --enable-rust-debug cargo will build a debug build. We use tracing to collect log output, and a handler (subscriber) is installed in main() if cargo is building a debug build. (The subscriber is not present in release builds, and hence logging is optimised out. Be aware that emitting records can slow down emacs considerably.)

The default handler is configured with the EMACSNG_LOG environment variable, in the format target=level. Crate names are targets, so to log for the webrender crate (which is named wrterm) at the info level, use EMACSNG_LOG=wrterm=info. Multiple filters can be separated with a comma, and filters are capable of advanced filtering with regexes. See the documentation for env_logger for more details.

Last update: May 2, 2024