Basic Usage

New App or Release

There are two main ways to organize code with rebar3 projects: either as a single application, or as an umbrella project.

Single application projects contain a lone top-level application at the root of the directory, with its Erlang source modules directly inside a src/ directory. This format is applicable to libraries to be published on github or in hex with the objective of making them shareable to the world, but can also be used with Releases, which allow to ship an Erlang runtime system that boots the application directly.

Umbrella projects’ defining characteristic is that they can contain multiple top-level Erlang/OTP applications, usually within a top-level apps/ or lib/ directory. Each of these applications may contain its own rebar.config file. This format is applicable to only for releases with one or more top-level applications.

Rebar3 comes with templates for creating either types of project, callable through the rebar3 new <template> <project-name> command. The <template> value can be any of:

  • app: a stateful OTP application with a supervision tree, as a single application project

  • lib: a library OTP application (without supervision trees), useful for grouping together various modules, as a single application project

  • release: an umbrella project ready to be released

  • escript: a special form of single application project that can be built as a runnable script

  • plugin: structure for a rebar3 plugin.

For example:

$ rebar3 new app myapp
===> Writing myapp/src/myapp_app.erl
===> Writing myapp/src/myapp_sup.erl
===> Writing myapp/src/
===> Writing myapp/rebar.config
===> Writing myapp/.gitignore
===> Writing myapp/LICENSE
===> Writing myapp/

For more information on new and available options check the docs on commands and to learn how to create and use custom templates go to the templates tutorial.

Adding Dependencies

Dependencies are listed in rebar.config file under the deps key:

{deps, [
        {elli, "~> 3.3.0"}, % package
        {elli, {git, "git://", {tag, "3.3.0"}}} % alternatively, source

Now you can add the dep to one of your project’s application’s .app.src file under applications so that Erlang knows the dependency is required for yours to work:

{application, <APPNAME>,
 [{description, ""},
  {vsn, "<APPVSN>"},
  {registered, []},
  {modules, []},
  {applications, [kernel,
  {mod, {<APPNAME>_app, []}},
  {env, []}

For more information on dependency handling view the dependency documentation


Only one command, compile, is required to fetch dependencies and compile all applications.

$ rebar3 compile
===> Verifying dependencies...
===> Fetching elli v3.3.0
===> Analyzing applications...
===> Compiling elli
===> Analyzing applications...
===> Compiling custom_hex_repos

Output Format

Output for installing dependencies, building releases and any other output written to disk is found in the _build directory at the root of the project.

└── default
  └── lib  
    └── elli

More about profiles and the _build directory can be found in the profiles documentation page.


Tests by default are expected to be found under the test/ directory, aside from eunit found within individual modules.

Dependencies that are only needed for running tests can be placed in the test profile:

{profiles, [
    {test, [
        {deps, [
            {meck, "0.9.0"}

Now the first time rebar3 ct is run meck will be installed to _build/test/lib/. But it will not be added to rebar.lock.

   └── test
     └── lib
       └── meck

Releases and Target Systems

Releases are built using relx.

Creating a new project with a release structure and default relx config in the rebar.config file run:

$ rebar3 new release myrel
===> Writing myrel/apps/myrel/src/myrel_app.erl
===> Writing myrel/apps/myrel/src/myrel_sup.erl
===> Writing myrel/apps/myrel/src/
===> Writing myrel/rebar.config
===> Writing myrel/config/sys.config
===> Writing myrel/config/vm.args
===> Writing myrel/.gitignore
===> Writing myrel/LICENSE
===> Writing myrel/

Looking in rebar.config we find a couple elements that were not there in our application example.

{relx, [{release, {myrel, "0.0.1"},

        {dev_mode, true},
        {include_erts, false},

        {extended_start_script, true}

{profiles, [
    {prod, [{relx, [{dev_mode, false},
                    {include_erts, true}]}

This configuration provides some nice defaults for building a release with relx for development (default profile) and for production (prod profile). When building a release for production we’ll most likely want to create a target system (include erts) and definitely will not want the release to contain symlinks to apps (dev_mode false).

$ rebar3 release
===> Verifying default dependencies...
===> Compiling myrel
===> Starting relx build process ...
===> Resolving OTP Applications from directories:          
===> Resolved myrel-0.1.0
===> Dev mode enabled, release will be symlinked
===> release successfully created!

With the default rebar.config, creating a compressed archive of the release as a target system is as simple as setting the profile to prod and running tar:

$ rebar3 as prod tar
===> Verifying dependencies...
===> Analyzing applications...
===> Compiling relx_overlays
===> Assembling release myrel-0.1.0...
===> Release successfully assembled: _build/prod/rel/myrel
===> Building release tarball myrel-0.1.0.tar.gz...
===> Tarball successfully created: _build/prod/rel/myrel/myrel-0.1.0.tar.gz

For more details go to the release section.

Last modified September 19, 2020: restructure all docs under new sections (6731f95)