> Documentation version: main. [HTML page](https://lukewilliamboswell.github.io/roc-blueprint/getting-started.html)

<a id="get-started"></a>

# Get started

[What Blueprint is](overview.md#a-small-blueprint-roc) showed what a
` Blueprint.roc ` says. This chapter makes one work on your machine. It
installs ` blueprint `, writes a first ` Blueprint.roc ` that needs nothing but
the binary, locks its download, runs a task in the environment it
describes, and then adds a tool from Nix.

<a id="install-blueprint"></a>

## Install blueprint

Each [release](https://github.com/lukewilliamboswell/roc-blueprint/releases) attaches a ` blueprint ` binary for x86\_64 Linux,
arm64 Linux and Apple Silicon macOS, named ` blueprint-x86_64-linux `,
` blueprint-aarch64-linux ` and ` blueprint-aarch64-darwin `, with their SHA-256
sums in ` blueprint.sha256 `. Download the one for your system from the
[latest release](https://github.com/lukewilliamboswell/roc-blueprint/releases/latest), check it and put it on your ` PATH `:

``` sh
sha256sum --check --ignore-missing blueprint.sha256
install -m 755 blueprint-x86_64-linux ~/.local/bin/blueprint
```

That is all the first project below needs. [Nix](https://nixos.org/download)
with flakes enabled is needed for the tools a project takes from a Nix
package source and for its sandboxed builds, and for nothing else:
` blueprint requirements ` says which of a project’s tasks need it. Where Nix
is installed, the same version also runs from the flake:

``` sh
nix run github:lukewilliamboswell/roc-blueprint/<version> -- --help
nix profile install github:lukewilliamboswell/roc-blueprint/<version>
```

In GitHub Actions, the
[` setup-blueprint `](https://lukewilliamboswell.github.io/roc-automation/actions.html#setup-blueprint)
action installs Nix and a release’s binary and checks its sum.

Loading a configuration runs one exact Roc nightly. The binary uses a ` roc ` on
` PATH ` when it is that nightly, and otherwise downloads it from its release,
checks it against a digest the binary records, and keeps it in its store of
downloads. Set ` ROC ` to choose the executable yourself; it must be that same
nightly.

<a id="write-a-first-blueprint-roc"></a>

## Write a first Blueprint.roc

Put this in ` Blueprint.roc ` at the root of your repository. The platform URL
is the latest release’s:

``` roc
app [config] { pf: platform "https://github.com/lukewilliamboswell/roc-blueprint/releases/download/0.11.0/EuSPs8vc71qJNFg29YzegvVRL1bR9pKqUYDHFiSCPTQ1.tar.zst" }

import pf.Recipes

config = [
	Name("my-project"),
	Environment("dev", [
		Programs([Fetch("roc-stable", Recipes.roc_nightly("nightly-2026-10-28-bad769b"))]),
		Expect(["git"]),
	]),
	Shell("default", [Use("dev")]),
	Task("version", [Use("dev"), Run(["roc-stable", "version"])]),
	Task("status", [Use("dev"), Run(["git", "status", "--short"])]),
]
```

**Use each release’s ` blueprint ` binary with that release’s platform URL.** The
two are built and tested together.

The file declares one environment, ` dev `. It has two commands:

- ` roc-stable ` is **fetched**: ` Recipes.roc_nightly ` says where that Roc
  nightly is downloaded from on each system, and ` Blueprint.lock ` will hold
  the digest of each download.

- ` git ` is **expected**: the machine must already have it. ` blueprint ` checks
  for it and installs nothing.

Each task names its environment and an exact argument list.

<a id="lock-the-downloads-and-run-something"></a>

## Lock the downloads and run something

``` sh
blueprint check          # validate Blueprint.roc; needs no lock
blueprint update         # record every download's digest in Blueprint.lock
blueprint run version    # run the task's command in dev
blueprint shell          # enter dev: your own shell, with roc-stable on PATH
blueprint requirements   # what each task needs of the machine
blueprint --help         # list this project's shells and tasks
```

` blueprint update ` is the only command that decides anything: it downloads
the compiler for your system, hashes it, and writes the digest for every
system to ` Blueprint.lock `. Every other command uses that file and fails if
it no longer matches ` Blueprint.roc `. ` blueprint run ` then downloads nothing:
the compiler is kept in a per-user store and checked against the lock on
every use.

None of this starts Nix, and ` blueprint requirements ` says so:

```
system x86_64-linux
providers: none
task version [dev]: programs roc-stable; expects git
task status [dev]: programs roc-stable; expects git
```

<a id="add-a-tool-from-nix"></a>

## Add a tool from Nix

A tool that should be installed, rather than fetched as one program or
expected of the machine, comes from a Nix package source. Declare the source,
and write each tool with the source’s name. Inside ` config `:

``` roc
Packages("nix", From(NixPackages("github:NixOS/nixpkgs/nixos-unstable"))),
Environment("native", [Tools(["nix#zig", "nix#pkg-config"])]),
Task("zig-version", [Use("native"), Run(["zig", "version"])]),
```

To give ` native ` the fetched compiler and ` git ` as well, start its settings
with ` Extend("dev") `.

The project now declares something Nix resolves, so ` blueprint update ` needs
Nix: it pins the source’s revision in the same ` Blueprint.lock `. After that,
only what uses the source starts Nix. ` blueprint run zig-version ` does;
` blueprint run version ` still does not, on a machine with Nix or without.
` blueprint update nix ` moves that one source and keeps every other pin and
digest.

<a id="commit-the-lock-not-the-generated-files"></a>

## Commit the lock, not the generated files

Commit ` Blueprint.roc ` and ` Blueprint.lock `. The lock is the authority: a
versioned S-expression listing each download with its digest and each pinned
source with its revision.

` blueprint ` keeps what it generates under ` .blueprint/ ` and writes a
` .gitignore ` there, so that directory never reaches a commit. If your
repository already tracks ` .blueprint/ `, untrack it once:

``` sh
git rm -r --cached .blueprint
```

<a id="where-to-go-next"></a>

## Where to go next

- [Write Blueprint.roc](configuration.md#top-level-settings) describes
  every setting.

- [Work without a provider](no-provider.md#the-store-of-downloads) says where
  downloads are kept and what a project without Nix can do.

- [Build artifacts and run workflows](builds.md#declare-a-build)
  covers sandboxed builds.

- [The examples](examples.md#run-an-example) are complete
  projects, attached to each release with that release’s platform URL.

