Nix-shell shebang: Difference between revisions
Update new cli section |
m change link to refer to below subsection |
||
| Line 8: | Line 8: | ||
The second shebang line declares the script language and the script dependencies. | The second shebang line declares the script language and the script dependencies. | ||
As of Nix 2.19.0 you can also use the new CLI <code>nix shell</code> and flakes to define shebangs. See [ | As of Nix 2.19.0 you can also use the new CLI <code>nix shell</code> and flakes to define shebangs. See [[Nix-shell shebang#New CLI alternatives|New CLI alternatives]] section. | ||
== Examples == | == Examples == | ||
Latest revision as of 13:55, 28 October 2026
You can use nix-shell as a script interpreter to
- run scripts in arbitrary languages
- provide dependencies with Nix
To do this, start the script with multiple shebang (#!) lines.
The first shebang line is always #! /usr/bin/env nix-shell.
The second shebang line declares the script language and the script dependencies.
As of Nix 2.19.0 you can also use the new CLI nix shell and flakes to define shebangs. See New CLI alternatives section.
Examples
Bash
To run bash scripts, set the interpreter with -i bash
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p bash
echo hello world
You can use nix-shell -p ... to add dependencies:
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p imagemagick cowsay
# scale image by 50%
convert "$1" -scale 50% "$1.s50.jpg" &&
cowsay "done $1.q50.jpg"
C#
Using file-based apps, new in .NET 10:
#!/usr/bin/env nix-shell
/*
#! nix-shell -i dotnet -p dotnetCorePackages.dotnet_10.sdk
*/
#:package Humanizer@2.14.1
using Humanizer;
Environment.CurrentDirectory = (string) AppContext.GetData("EntryPointFileDirectoryPath")!; // equivalent of `cd $(dirname $0)`
var dotNet9Released = DateTimeOffset.Parse("2024-12-03");
var since = DateTimeOffset.Now - dotNet9Released;
Console.WriteLine($"It has been {since.Humanize()} since .NET 9 was released.");
Haskell
#! /usr/bin/env nix-shell
#! nix-shell -p "haskellPackages.ghcWithPackages (p: with p; [turtle])" -i runghc
{-# LANGUAGE OverloadedStrings #-}
import Turtle
main = echo "Hello world!"
Lua
Stable CLI
#!/usr/bin/env nix-shell
--[[
#!nix-shell -i lua -p lua5_3
--]]
print("Hello, world!")
Pinned and eval-cached
#!/usr/bin/env nix
--[[
#!nix shell github:NixOS/nixpkgs?ref=88a6078fc5d104f480d1b4a0b58ffec5de965b1b#lua5_3 -c lua
--]]
print("Hello, world!")
Python
#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p python3
print("hello world")
#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p python3Packages.pillow python3Packages.ansicolor
# scale image by 50%
import sys, PIL.Image, ansicolor
path = sys.argv[1]
image = PIL.Image.open(path)
factor = 0.5
image = image.resize((round(image.width * factor), round(image.height * factor)))
path = path + ".s50.jpg"
image.save(path)
print(ansicolor.green(f"done {path}"))
Rust
No dependencies
#!/usr/bin/env nix-shell
#![allow()] /*
#!nix-shell -i bash -p rustc
rsfile="$(readlink -f $0)"
binfile="/tmp/$(basename "$rsfile").bin"
rustc "$rsfile" -o "$binfile" --edition=2021 && exec "$binfile" $@ || exit $?
*/
fn main() {
for argument in std::env::args().skip(1) {
println!("{}", argument);
};
println!("{}", std::env::var("HOME").expect(""));
}
With dependencies
uses rust-script
#!/usr/bin/env nix-shell
//! ```cargo
//! [dependencies]
//! time = "0.1.25"
//! ```
/*
#!nix-shell -i rust-script -p rustc -p rust-script -p cargo
*/
fn main() {
for argument in std::env::args().skip(1) {
println!("{}", argument);
};
println!("{}", std::env::var("HOME").expect(""));
println!("{}", time::now().rfc822z());
}
Wolfram Language
Using Woxi, the Rust reimplementation.
#!/usr/bin/env nix-shell
(*
#! nix-shell -p woxi -i woxi
*)
RandomInteger[{1, 9}, 5] // Map[#^2&] // Map[Print]
Pinning nixpkgs
To pin nixpkgs to a specific version, add a third shebang line:
#! /usr/bin/env nix-shell
#! nix-shell -i bash
#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/aed4b19d312525ae7ca9bceb4e1efe3357d0e2eb.tar.gz
echo hello world
New CLI alternatives
It is also possible to make it work with the new Nix command (nix3), like so:
#! /usr/bin/env nix
#! nix nixpkgs#bash nixpkgs#hello nixpkgs#cowsay --command bash
hello | cowsay
Alternatively, using a single line (using env -S):
#! /usr/bin/env -S nix shell nixpkgs#bash nixpkgs#hello nixpkgs#cowsay --command bash
hello | cowsay
See this Nix manual page for more details on nix3 shebangs.
Performance
TODO ... why the startup delay? how to make it faster?
- Speeding up nix-shell shebang
- cached-nix-shell - Instant startup time for nix-shell
- Nix Flakes, Part 2: Evaluation caching - Tweag