Skip to main content
Noir’s module and package system follows the same conventions as Rust’s newer module system. Modules help you organize code across multiple files, and packages group crates that are managed together via Nargo.toml.

Modules

Declaring a module

The compiler does not automatically scan files for modules. You must explicitly declare each module with the mod keyword in the file that uses it. src/main.nr
src/foo.nr
The compiler sees mod foo and looks for either src/foo.nr or src/foo/mod.nr.
It is an error to have both src/foo.nr and src/foo/mod.nr in the same project.

Sub-modules

A module can declare its own sub-modules. The compiler looks for sub-module files relative to the parent module’s directory: src/main.nr
src/foo.nr
src/foo/bar.nr
The module hierarchy looks like:

Referencing modules

All modules are accessible from the crate:: namespace. Use crate::path to reference any module from anywhere in the project:
Use super:: to refer to the parent module:

Visibility

Modules are private by default. Use pub or pub(crate) to control visibility:

use statements

Import names from other modules with use:
Import multiple items at once with curly braces:
Import an entire module:

Re-exporting with pub use

use declarations are private to their containing module by default. Mark them pub or pub(crate) to re-export names:

Crates and packages

Crate types

A crate is the smallest unit the Noir compiler processes. There are three kinds:
Binary crates compile to ACIR circuits that you can prove. They must have a main function.The crate root file must be named src/main.nr.
Library crates define reusable functionality without a main function. They do not compile to ACIR directly.The crate root file must be named src/lib.nr.
Contract crates compile to ACIR and are deployed to the Aztec network. They expose a collection of functions rather than a single main.

Packages

A package is a collection of one or more crates, described by a Nargo.toml file. A package must contain either a library crate or a binary crate, but not both. A minimal Nargo.toml for a binary:
For a library:

Dependencies

Git dependencies

Specify a git dependency with a tag for reproducible builds:
If the package is in a subdirectory of the repo, add directory:
Always specify a tag. Without one, your build will be non-reproducible — the dependency may change on every compile.

Local (path) dependencies

Reference a local library with path:
Example project layout:

Importing dependencies

After declaring a dependency in Nargo.toml, import it in your Noir code:

Transitive dependencies

When you import a dependency, you also get access to all of that package’s dependencies:

The standard library

The Noir standard library (std) is always available. Import items from it with use std::...:
Common standard library modules include:

Workspaces

A workspace manages multiple related Noir packages in a single repository. Create a top-level Nargo.toml with a [workspace] section:
Example project structure:
  • members — which packages are included in the workspace.
  • default-member — the package processed by commands when no --package flag is given.
Within a workspace, reference sibling libraries using path dependencies:
Avoid nesting regular packages inside a workspace — certain nargo commands walk up to find the topmost Nargo.toml and may run on an unintended package.