Getting started

Nickel is still young and the installation process is not yet optimal. Sorry about that! We are focused on improving the experience, so stay tuned.

We give three alternative ways of obtaining a running Nickel executable:
  1. Using Nix
  2. Using Cargo
  3. Using Docker
If you have neither of these tools, Nix is the preferred way. If you don't have Nix but you are a user of Cargo or Docker, you may prefer the corresponding installation method.

Get a Nickel binary using Nix


With a recent version of Nix (> 2.4.0), you can build and run Nickel in one shot. If you haven't installed Nix yet, please follow this installation guide. Once Nix is installed, use nix run to start Nickel and append -- args to pass arguments to the Nickel executable (here we launch an REPL session)

nix run --experimental-features "flakes nix-command" github:tweag/nickel -- repl


If you are planning to try Nickel a bit more extensively, you can install the Nickel binary using nix profile:

nix profile install github:tweag/nickel
nickel repl

Get a Nickel binary using Cargo

If you are a Rust developer, the Cargo build tool is an alternative way to install a Nickel binary:

cargo install nickel-lang
nickel repl

Get a Docker image

A last alternative is to use Docker: you can download the nickel-0.1.0-docker-image.tar.gz. Please refer to the official Docker documentation to know how to load and run a Docker image.

Write your first configuration

Nickel has advanced features to help you handle and organize complex configurations (gradual typing, contracts, a merge system, and so on). But you'll only have to deal with any of this once you need to. Writing a basic configuration is as simple as writing JSON or YAML. Let's write a manifest of a fictional app:

  name = "example",
  description = m%"
    This is an awesome software I'm developing.
    Please use it!
  version = "0.1.1",
  main = "index.js",
  keywords = ["example", "config"],
  scripts = {
    test = m%" --option --install example --version "0.1.1""%m,
    do_stuff = " subcommand",
  contributors = [{
      name = "John Doe",
      email = ""
    }, {
      name = "Ivy Lane",
      url = ""
  dependencies = {
    dep1 = "^1.0.0",
    dep3 = "6.7"

This program is composed of a record. A record is the same thing as an object in JSON, that is a list of key-value pairs delimited by { and }. In general, the values of Nickel map directly to corresponding values in JSON (excluding functions). Thus, the basic datatypes of Nickel are the same as in JSON:
  • Records (objects), delimited by { and }.
  • Strings, delimited by ". The sequence m%" and "%m delimits multiline strings.
  • Numbers.
  • Lists, delimited by [ and ] and separated by ,.

Multiline strings are an alternative way of defining strings. Line 11 is an example of such a string. Without diving into the details, multiline strings are useful for:
  • Writing strings spanning several lines, as their name suggests. Multiline strings can be indented at the same level as the surrounding code while still producing the expected result (the common indentation prefix is stripped).
  • Writing strings with special characters without having to escape them.
In our example, using a multiline string saves us from escaping the recurring double quotes ".


The ultimate goal of a Nickel program is to produce a static configuration. To do so, save the example above to example.ncl and run nickel export:

./result/bin/nickel -f example.ncl export --format yaml
  - email:
    name: John Doe
  - name: Ivy Lane
  dep1: ^1.0.0
  dep3: "6.7"
description: "This is an awesome software I'm developing.\nPlease use it!"
  - example
  - config
main: index.js
name: example
  do_stuff: subcommand
  test: " --option --install example --version \"0.1.1\""
version: 0.1.1

Nickel currently supports exporting to and importing from YAML, TOML and JSON.


Nickel is a programming language. This allows you not only to describe, but to generate data. There's repetition in our previous example:

name = "example",
version = "0.1.1",
scripts = {
  test = m%" --option --install example --version "0.1.1""%m,

The version 0.1.1 appears both in version and scripts.test. The name example appears both in name and scripts.test as well. Pure aesthetics aside, a more serious issue is inconsistency. If you bump the version number in version, you may forget to do so in the scripts.test as well, ending up with incoherent version numbers in the same configuration. To remedy the problem, let's have a single source of truth by reusing the value of name and version in scripts.test, using the string interpolation syntax %{expr}:

name = "example",
version = "0.1.1",
scripts = {
  test = m%" --option --install %{name} --version "%{version}""%m

Now, if we change version to 0.1.2 and export the result, the test script invocation is updated as well:

# [...]
  do_stuff: subcommand
  test: " --option --install example --version \"0.1.2\""
version: 0.1.2

Going further

This short introduction should get you started. Nickel is a full-fledged programming language, featuring higher-order functions, gradual typing, contracts, and more! To explore further, read the user manual. You will also find examples in the repository. For an overview of Nickel and the motivations behind it, see the README and the design rationale document.