Pin down your software

Declaratively configure your projects, get reproducible results.

import * as garn from "";
import * as pkgs from "";

export const backend = garn.go.mkGoProject({
description: "A Go server",
src: ".",
goVersion: "1.21",
.withDevTools([pkgs.ripgrep, pkgs.air])
.addCheck("no-todos-allowed", "! rg -i todo .")
.addExecutable("dev-server", "air main.go");
$ garn chec

Have you ever worked on a project and realized you had the wrong node version?

Or golang? Or prettier? Or some other tool? garn manages all of your project's dependencies in encapsulated environments. Compilers, code-generators, formatters, test-runners, linters and more.

import * as garn from ""; export const frontend = garn.javascript.mkNpmProject({ description: "my frontend project", src: ".", nodeVersion: "18", });
$ node node: command not found $ garn enter frontend [garn] Entering frontend shell. Type 'exit' to exit. $ node --version v18.17.1

Have you ever pushed to GitHub over and over again, just to get CI working?

garn allows to declare reproducible checks that you can run locally in completely deterministic environments. And if you enable CI (like garnix) on your GitHub repo, you get the same exact checks there.

import * as garn from ""; import * as nixpkgs from ""; export const backend = garn.haskell .mkHaskellProject({ description: "my Haskell backend", executable: "server", compiler: "ghc94", src: ".", }) .withDevTools([nixpkgs.hlint]) .addCheck("hlint", "hlint *.hs");
$ garn check [...] check> No hints

Have you ever written a bash script that worked totally fine on your machine, but crashed on someone else's?

Well, it was probably their fault for not having the right tools installed... garn allows you to add deterministic scripts to your projects that run the same everywhere. Use them to run dev servers, bundle Javascript, format source code, run code generators and more.

export const backend = garn.go.mkGoProject({ description: "Go backend", src: ".", goVersion: "1.21", }) .withDevTools([pkgs.protobuf, pkgs.protoc_gen_go]) .addExecutable("codegen", "protoc --go_out=out protobufs/*.proto");
$ protoc protobufs/*.proto protoc: command not found $ garn run backend.codegen

Frequently Asked Questions

How does garn differ from docker, vagrant, etc.?

garn uses nix instead of containers or VMs to provide dependencies. These dependencies will all be installed into the nix store (in /nix/store) and will be provided from there in the environments that you create with garn.

That means that garn scripts and checks and everything else you do when developing with garn runs natively on your machine. So there is no overhead that you would get when using VMs or containers on non-linux hosts.

That also means that -- when entering an environment with garn enter -- you can use your personal editor or other globally installed tools with no additional work.

How does garn differ from 'npm', 'cabal' and other language-specific tools?

garn is language agnostic. That means you can use it in projects that mix multiple languages and have the same experience and workflows for all sub-projects. It also means that programmers that are unfamiliar with the toolchain of a project can use garn to get started quickly.

What languages does garn support?

garn currently supports Go, Npm and Haskell. If you'd like to see support for other languages or toolchains please let us know.

How can I configure LSP to get error messages and auto-completion for garn.ts in my editor?

garn.ts files are powered by Deno. A lot of the convenience and power for editing your garn.ts files comes from having a working Deno LSP. There are two ways of setting up LSP for editing garn.ts files: using `garn edit`, which provides a properly-configured editor, or using garn to provide deno and setting up your editor configuration yourself.

garn edit

garn can download and configure vscodium for you — just type garn edit. It will spin up a vscodium editor that is pre-configured for editing garn.ts files. It won't use or modify your local vscodium settings, if you have any. You can can add it to your garn.ts file like this:

Installing the Deno LSP and configuring your editor

Alternatively you can install deno (including the Deno LSP) with garn itself:

import * as garn from ""; export const deno = garn.mkProject({ description: "garn configuration environment", defaultEnvironment: garn.emptyEnvironment.withDevTools([pkgs.deno]), }, {});

garn enter deno will then drop you in a shell where deno is available.

For configuring your editor to use Deno's LSP refer to Deno's environment setup documentation.