Getting started
This project has a single dependency; Nix. It will be used to pull in all other dependencies. It can be installed by following the instructions over there: https://nixos.org/download.html#nix-quick-install
Now that's done, got to your project root and create an empty devshell.toml
.
There are different ways to load that config depending on your preferences:
Nix (non-flake)
Add another file called shell.nix
with the following content. This file will
contain some nix code. Don't worry about the details.
{ system ? builtins.currentSystem }:
let
src = fetchTarball "https://github.com/numtide/devshell/archive/main.tar.gz";
devshell = import src { inherit system; };
in
devshell.fromTOML ./devshell.toml
NOTE: it's probably a good idea to pin the dependency by replacing
main
with a git commit ID.
Now you can enter the developer shell for the project:
$ nix-shell
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
these 4 derivations will be built:
/nix/store/nvbfq9h68r63k5jkfnbimny3b35sx0fs-devshell-bashrc.drv
/nix/store/ppfyf9zv023an8477hcbjlj0rbyvmwq7-devshell.env.drv
/nix/store/8027cgy3xcinb59aaynh899q953dnzms-devshell-bin.drv
/nix/store/w33zl180ni880p18sls5ykih88zkmkqk-devshell.drv
building '/nix/store/nvbfq9h68r63k5jkfnbimny3b35sx0fs-devshell-bashrc.drv'...
building '/nix/store/ppfyf9zv023an8477hcbjlj0rbyvmwq7-devshell-env.drv'...
created 1 symlinks in user environment
building '/nix/store/8027cgy3xcinb59aaynh899q953dnzms-devshell-bin.drv'...
building '/nix/store/w33zl180ni880p18sls5ykih88zkmkqk-devshell.drv'...
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
🔨 Welcome to devshell
[general commands]
menu - prints this menu
[devshell]$
Nix Flakes
For users of nix flakes, a default template is provided to get you up and running.
nix flake new -t "github:numtide/devshell" project/
cd project/
# enter the shell
nix develop # or `direnv allow` if you want to use direnv
Find templates/gettingStartedExample
in this repository for a working example of the additional configuration below: env
, packages
, and serviceGroups
.
Adding environment variables
Environment variables that are specific to the project can be added with the
[[env]]
declaration. Each environment variable is an entry in an array, and
will be set in the order that they are declared.
Eg:
[[env]]
name = "GO111MODULE"
value = "on"
There are different ways to set the environment variables. Look at the schema to find all the ways. But in short:
- Use the
value
key to set a fixed env var. - Use the
eval
key to evaluate the value. This is useful when one env var depends on the value of another. - Use the
prefix
key to prepend a path to an environment variable that uses the path separator. LikePATH
.
Adding new commands
Devshell also supports adding new commands to the environment. Those are displayed on devshell entry so that the user knows what commands are available to them.
In order to bring in new dependencies, you can either add them to
devshell.packages
or as an entry in the [[commands]]
list (see TOML docs). Commands are also added to the
menu so they might be preferable for discoverability.
As an exercise, add the following snippet to your devshell.toml
:
[[commands]]
package = "go"
Then re-enter the shell with nix-shell
/nix develop
/direnv reload
. You should see something like this:
$ nix-shell
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
these 4 derivations will be built:
/nix/store/nvbfq9h68r63k5jkfnbimny3b35sx0fs-devshell-bashrc.drv
/nix/store/ppfyf9zv023an8477hcbjlj0rbyvmwq7-devshell.env.drv
/nix/store/8027cgy3xcinb59aaynh899q953dnzms-devshell-bin.drv
/nix/store/w33zl180ni880p18sls5ykih88zkmkqk-devshell.drv
building '/nix/store/nvbfq9h68r63k5jkfnbimny3b35sx0fs-devshell-bashrc.drv'...
building '/nix/store/ppfyf9zv023an8477hcbjlj0rbyvmwq7-devshell-env.drv'...
created 1 symlinks in user environment
building '/nix/store/8027cgy3xcinb59aaynh899q953dnzms-devshell-bin.drv'...
building '/nix/store/w33zl180ni880p18sls5ykih88zkmkqk-devshell.drv'...
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
🔨 Welcome to devshell
[general commands]
menu - prints this menu
go - The Go Programming language
[devshell]$
Now the go
program is available in the environment and can be used to
develop Go programs. This can easily be adapted to any language.
Similarly, you could also add go to the packages list, in which case it would not appear in the menu:
[devshell]
packages = [
"go"
]
Finding packages
Check out the Nix package repository.
Note that it is also possible to use specific versions for some packages - e.g. for NodeJS, search the repo & use like this:
[[commands]]
package = "nodejs-17_x" # https://search.nixos.org/packages?type=packages&query=nodejs
name = "node"
help = "NodeJS"
Or another example:
[devshell]
packages = [
"python27", # 2.7
"python311", # 3.11
]
Adding background services
Many projects need background services to be running during development or to run tests (e.g. a database, caching server, webserver, ...). This is supported in devshell through the concept of service groups.
A service group defines a collection of long-running processes that can be started and stopped.
An example service group could be configured like this:
[serviceGroups.database]
description = "Runs a database in the backgroup"
[serviceGroups.database.services.postgres]
command = "postgres"
[serviceGroups.database.services.memcached]
command = "memcached"
This will add two commands to the devshell: database:start
and
database:stop
. database:start
starts the defined services in the database
group in the foreground and shows their output. database:stop
can be executed
in a different shell to stop the processes (or press Ctrl-C in the main shell).
Wrapping up
devshell is extensible in many different ways. In the next chapters we will discuss the various ways in which it can be adapted to your project's needs.