Skip to content

Instantly share code, notes, and snippets.

@aldur
Created November 30, 2025 18:59
Show Gist options
  • Select an option

  • Save aldur/518cc92d30a897b226ed18f7f10926cb to your computer and use it in GitHub Desktop.

Select an option

Save aldur/518cc92d30a897b226ed18f7f10926cb to your computer and use it in GitHub Desktop.
nixpkgs.writers

Data format writers {#sec-functions-library-data}

writers.data.makeDataWriter {#function-library-lib.writers.data.makeDataWriter}

Creates a transformer function that writes input data to disk, transformed by both the input and output arguments.

Example {#data-makeDataWriter-examples}

writeJSON = makeDataWriter { input = builtins.toJSON; output = "cp $inputPath $out"; };
myConfig = writeJSON "config.json" { hello = "world"; }

Type {#data-makeDataWriter-type}

makeDataWriter :: input -> output -> nameOrPath -> data -> (any -> string) -> string -> string -> any -> derivation

input :: T -> string: function that takes the nix data and returns a string
output :: string: script that takes the $inputFile and write the result into $out
nameOrPath :: string: if the name contains a / the files gets written to a sub-folder of $out. The derivation name is the basename of this argument.
data :: T: the data that will be converted.

writers.data.writeJSON {#function-library-lib.writers.data.writeJSON}

Writes the content to a JSON file.

Example {#data-writeJSON-examples}

writeJSON "data.json" { hello = "world"; }

writers.data.writeTOML {#function-library-lib.writers.data.writeTOML}

Writes the content to a TOML file.

Example {#data-writeTOML-examples}

writeTOML "data.toml" { hello = "world"; }

writers.data.writeYAML {#function-library-lib.writers.data.writeYAML}

Writes the content to a YAML file.

Example {#data-writeYAML-examples}

writeYAML "data.yaml" { hello = "world"; }

Script writers {#sec-functions-library-scripts}

writers.scripts.makeScriptWriter {#function-library-lib.writers.scripts.makeScriptWriter}

makeScriptWriter returns a derivation which creates an executable script.

Inputs {#scripts-makeScriptWriter-inputs}

config (AttrSet) : interpreter (String) : the interpreter to use for the script. : check (String) : A command to check the script. For example, this could be a linting check. : makeWrapperArgs (Optional, [ String ], Default: []) : Arguments forwarded to (makeWrapper)[#fun-makeWrapper].

nameOrPath (String) : The name of the script or the path to the script.

When a string starting with "/" is passed, the script will be created at the specified path in $out. I.e. "/bin/hello" will create a script at $out/bin/hello.

Any other string is interpreted as a filename. It must be a POSIX filename starting with a letter, digit, dot, or underscore. Spaces or special characters are not allowed.

content (String) : The content of the script.

:::{.note} This function is used as base implementation for other high-level writer functions.

For example, writeBash can (roughly) be implemented as:

writeBash = makeScriptWriter { interpreter = "${pkgs.bash}/bin/bash"; }

:::

Examples {#scripts-makeScriptWriter-examples}

:::{.example}

pkgs.writers.makeScriptWriter dash example

:b makeScriptWriter { interpreter = "${pkgs.dash}/bin/dash"; } "hello" "echo hello world"
-> /nix/store/indvlr9ckmnv4f0ynkmasv2h4fxhand0-hello

The above example creates a script named hello that outputs hello world when executed.

> /nix/store/indvlr9ckmnv4f0ynkmasv2h4fxhand0-hello
hello world

:::

:::{.example}

pkgs.writers.makeScriptWriter python example

:b makeScriptWriter { interpreter = "${pkgs.python3}/bin/python"; } "python-hello" "print('hello world')"
-> /nix/store/4kvby1hqr45ffcdrvfpnpj62hanskw93-python-hello
> /nix/store/4kvby1hqr45ffcdrvfpnpj62hanskw93-python-hello
hello world

:::

writers.scripts.makeBinWriter {#function-library-lib.writers.scripts.makeBinWriter}

makeBinWriter returns a derivation which compiles the given script into an executable format.

:::{.note} This function is the base implementation for other compile language writers, such as writeHaskell and writeRust. :::

Inputs {#scripts-makeBinWriter-inputs}

config (AttrSet) : compileScript (String) : The script that compiles the given content into an executable.

: strip (Boolean, Default: true) : Whether to strip the executable or not.

: makeWrapperArgs (Optional, [ String ], Default: []) : Arguments forwarded to (makeWrapper)[#fun-makeWrapper]

nameOrPath (String) : The name of the script or the path to the script.

When a string starting with "/" is passed, the script will be created at the specified path in $out. For example, "/bin/hello" will create a script at $out/bin/hello.

Any other string is interpreted as a filename. It must be a POSIX filename starting with a letter, digit, dot, or underscore. Spaces or special characters are not allowed.

Examples {#scripts-makeBinWriter-examples}

:::{.example}

pkgs.writers.makeBinWriter example

// main.c
#include <stdio.h>

int main()
{
    printf("Hello, World!\n");
    return 0;
}
:b makeBinWriter { compileScript = "${pkgs.gcc}/bin/gcc -o $out $contentPath"; } "hello" ./main.c
out -> /nix/store/f6crc8mwj3lvcxqclw7n09cm8nb6kxbh-hello

The above example creates an executable named hello that outputs Hello, World! when executed.

> /nix/store/f6crc8mwj3lvcxqclw7n09cm8nb6kxbh-hello
Hello, World!

:::

writers.scripts.writeBash {#function-library-lib.writers.scripts.writeBash}

Like writeScript but the first line is a shebang to bash Can be called with or without extra arguments.

Examples {#scripts-writeBash-examples}

:::{.example}

writeBash without arguments

writeBash "example" ''
echo hello world
''

:::

:::{.example}

writeBash with arguments

writeBash "example"
{
  makeWrapperArgs = [
    "--prefix" "PATH" ":" "${lib.makeBinPath [ pkgs.hello ]}"
  ];
}
''
  hello
''

:::

writers.scripts.writeBashBin {#function-library-lib.writers.scripts.writeBashBin}

Like writeScriptBin but the first line is a shebang to bash

Can be called with or without extra arguments.

Examples {#scripts-writeBashBin-examples}

:::{.example}

pkgs.writers.writeBashBin example without arguments

writeBashBin "example" ''
  echo hello world
''

:::

:::{.example}

pkgs.writers.writeBashBin example with arguments

writeBashBin "example"
{
  makeWrapperArgs = [
    "--prefix" "PATH" ":" "${lib.makeBinPath [ pkgs.hello ]}"
  ];
}
''
  hello
''

:::

writers.scripts.writeDash {#function-library-lib.writers.scripts.writeDash}

Like writeScript but the first line is a shebang to dash

Can be called with or without extra arguments.

Example {#scripts-writeDash-examples}

:::{.example}

pkgs.writers.writeDash example without arguments

writeDash "example" ''
  echo hello world
''

:::

:::{.example}

pkgs.writers.writeDash example with arguments

writeDash "example"
{
  makeWrapperArgs = [
    "--prefix" "PATH" ":" "${lib.makeBinPath [ pkgs.hello ]}"
  ];
}
''
  hello
''

:::

writers.scripts.writeDashBin {#function-library-lib.writers.scripts.writeDashBin}

Like writeScriptBin but the first line is a shebang to dash

Can be called with or without extra arguments.

Examples {#scripts-writeDashBin-examples}

:::{.example}

pkgs.writers.writeDashBin without arguments

writeDashBin "example" ''
  echo hello world
''

:::

:::{.example}

pkgs.writers.writeDashBin with arguments

writeDashBin "example"
{
  makeWrapperArgs = [
    "--prefix" "PATH" ":" "${lib.makeBinPath [ pkgs.hello ]}"
  ];
}
''
  hello
''

:::

writers.scripts.writeFish {#function-library-lib.writers.scripts.writeFish}

Like writeScript but the first line is a shebang to fish

Can be called with or without extra arguments.

:::{.example}

pkgs.writers.writeFish without arguments

writeFish "example" ''
  echo hello world
''

:::

:::{.example}

pkgs.writers.writeFish with arguments

writeFish "example"
{
  makeWrapperArgs = [
    "--prefix" "PATH" ":" "${lib.makeBinPath [ pkgs.hello ]}"
  ];
}
''
  hello
''

:::

writers.scripts.writeFishBin {#function-library-lib.writers.scripts.writeFishBin}

Like writeScriptBin but the first line is a shebang to fish

Can be called with or without extra arguments.

Examples {#scripts-writeFishBin-examples}

:::{.example}

pkgs.writers.writeFishBin without arguments

writeFishBin "example" ''
  echo hello world
''

:::

:::{.example}

pkgs.writers.writeFishBin with arguments

writeFishBin "example"
{
  makeWrapperArgs = [
    "--prefix" "PATH" ":" "${lib.makeBinPath [ pkgs.hello ]}"
  ];
}
''
  hello
''

:::

writers.scripts.writeBabashka {#function-library-lib.writers.scripts.writeBabashka}

writeBabashka takes a name, an attrset with babashka interpreter and linting check (both optional) and some babashka source code and returns an executable.

pkgs.babashka-unwrapped is used as default interpreter for small closure size. If dependencies needed, use pkgs.babashka instead. Pass empty string to check to disable the default clj-kondo linting.

Examples {#scripts-writeBabashka-examples}

:::{.example}

pkgs.writers.writeBabashka with empty arguments

writeBabashka "example" { } ''
  (println "hello world")
''

:::

:::{.example}

pkgs.writers.writeBabashka with arguments

writeBabashka "example"
{
  makeWrapperArgs = [
    "--prefix" "PATH" ":" "${lib.makeBinPath [ pkgs.hello ]}"
  ];
}
''
  (require '[babashka.tasks :as tasks])
  (tasks/shell "hello" "-g" "Hello babashka!")
''

:::

:::{.note} Babashka needs Java for fetching dependencies. Wrapped babashka contains jdk, pass wrapped version pkgs.babashka to babashka if dependencies are required.

For example:

writeBabashka "example"
{
  babashka = pkgs.babashka;
}
''
  (require '[babashka.deps :as deps])
  (deps/add-deps '{:deps {medley/medley {:mvn/version "1.3.0"}}})
  (require '[medley.core :as m])
  (prn (m/index-by :id [{:id 1} {:id 2}]))
''

:::

:::{.note} Disable clj-kondo linting:

writeBabashka "example"
{
  check = "";
}
''
  (println "hello world")
''

:::

writers.scripts.writeBabashkaBin {#function-library-lib.writers.scripts.writeBabashkaBin}

writeBabashkaBin takes the same arguments as writeBabashka but outputs a directory (like writeScriptBin)

writers.scripts.writeGuile {#function-library-lib.writers.scripts.writeGuile}

writeGuile returns a derivation that creates an executable Guile script.

Inputs {#scripts-writeGuile-inputs}

nameOrPath (String) : Name of or path to the script. The semantics is the same as that of makeScriptWriter.

config (AttrSet) : guile (Optional, Derivation, Default: pkgs.guile) : Guile package used for the script. : libraries (Optional, [ Derivation ], Default: []) : Extra Guile libraries exposed to the script. : r6rs and r7rs (Optional, Boolean, Default: false) : Whether to adapt Guile’s initial environment to better support R6RS/ R7RS. See the Guile Reference Manual for details. : srfi (Optional, [ Int ], Default: []) : SRFI module to be loaded into the interpreter before evaluating a script file or starting the REPL. See the Guile Reference Manual to know which SRFI are supported. : Other attributes are directly passed to makeScriptWriter.

content (String) : Content of the script.

Examples {#scripts-writeGuile-examples}

:::{.example}

pkgs.writers.writeGuile with default config

writeGuile "guile-script" { }
''
  (display "Hello, world!")
''

:::

:::{.example}

pkgs.writers.writeGuile with SRFI-1 enabled and extra libraries

writeGuile "guile-script" {
  libraries = [ pkgs.guile-semver ];
  srfi = [ 1 ];
}
''
  (use-modules (semver))
  (make-semver 1 (third '(2 3 4)) 5) ; => #<semver 1.4.5>
''

:::

writers.scripts.writeGuileBin {#function-library-lib.writers.scripts.writeGuileBin}

writeGuileBin takes the same arguments as writeGuile but outputs a directory (like writeScriptBin)

writers.scripts.writeHaskell {#function-library-lib.writers.scripts.writeHaskell}

writeHaskell takes a name, an attrset with libraries and haskell version (both optional) and some haskell source code and returns an executable.

Examples {#scripts-writeHaskell-examples}

:::{.example}

pkgs.writers.writeHaskell usage example

writeHaskell "missiles" { libraries = [ pkgs.haskellPackages.acme-missiles ]; } ''
  import Acme.Missiles

  main = launchMissiles
'';

:::

writers.scripts.writeHaskellBin {#function-library-lib.writers.scripts.writeHaskellBin}

writeHaskellBin takes the same arguments as writeHaskell but outputs a directory (like writeScriptBin)

writers.scripts.writeNim {#function-library-lib.writers.scripts.writeNim}

writeNim takes a name, an attrset with an optional Nim compiler, and some Nim source code, returning an executable.

Examples {#scripts-writeNim-examples}

:::{.example}

pkgs.writers.writeNim usage example

  writeNim "hello-nim" { nim = pkgs.nim2; } ''
    echo "hello nim"
  '';

:::

writers.scripts.writeNimBin {#function-library-lib.writers.scripts.writeNimBin}

writeNimBin takes the same arguments as writeNim but outputs a directory (like writeScriptBin)

writers.scripts.writeNu {#function-library-lib.writers.scripts.writeNu}

Like writeScript but the first line is a shebang to nu

Can be called with or without extra arguments.

Examples {#scripts-writeNu-examples}

:::{.example}

pkgs.writers.writeNu without arguments

writeNu "example" ''
  echo hello world
''

:::

:::{.example}

pkgs.writers.writeNu with arguments

writeNu "example"
  {
    makeWrapperArgs = [
      "--prefix" "PATH" ":" "${lib.makeBinPath [ pkgs.hello ]}"
    ];
  }
  ''
    hello
  ''

:::

writers.scripts.writeNuBin {#function-library-lib.writers.scripts.writeNuBin}

Like writeScriptBin but the first line is a shebang to nu

Can be called with or without extra arguments.

Examples {#scripts-writeNuBin-examples}

:::{.example}

pkgs.writers.writeNuBin without arguments

writeNuBin "example" ''
  echo hello world
''

:::

:::{.example}

pkgs.writers.writeNuBin with arguments

writeNuBin "example"
  {
    makeWrapperArgs = [
      "--prefix" "PATH" ":" "${lib.makeBinPath [ pkgs.hello ]}"
    ];
  }
  ''
    hello
  ''

:::

writers.scripts.makeRubyWriter {#function-library-lib.writers.scripts.makeRubyWriter}

makeRubyWriter takes ruby and compatible rubyPackages and produces ruby script writer, If any libraries are specified, ruby.withPackages is used as interpreter, otherwise the "bare" ruby is used.

writers.scripts.writeRuby {#function-library-lib.writers.scripts.writeRuby}

Like writeScript but the first line is a shebang to ruby

Examples {#scripts-writeRuby-examples}

:::{.example}

pkgs.writers.writeRuby usage example

writeRuby "example" { libraries = [ pkgs.rubyPackages.git ]; } ''
 puts "hello world"
''

:::

writers.scripts.makeLuaWriter {#function-library-lib.writers.scripts.makeLuaWriter}

makeLuaWriter takes lua and compatible luaPackages and produces lua script writer, which validates the script with luacheck at build time. If any libraries are specified, lua.withPackages is used as interpreter, otherwise the "bare" lua is used.

writers.scripts.writeLua {#function-library-lib.writers.scripts.writeLua}

writeLua takes a name an attributeset with libraries and some lua source code and returns an executable (should also work with luajit)

Examples {#scripts-writeLua-examples}

:::{.example}

pkgs.writers.writeLua usage example

writeLua "test_lua" { libraries = [ pkgs.luaPackages.say ]; } ''
  s = require("say")
  s:set_namespace("en")

  s:set('money', 'I have %s dollars')
  s:set('wow', 'So much money!')

  print(s('money', {1000})) -- I have 1000 dollars

  s:set_namespace("fr") -- switch to french!
  s:set('wow', "Tant d'argent!")

  print(s('wow')) -- Tant d'argent!
  s:set_namespace("en")  -- switch back to english!
  print(s('wow')) -- So much money!
''

:::

writers.scripts.writeJS {#function-library-lib.writers.scripts.writeJS}

writeJS takes a name an attributeset with libraries and some JavaScript sourcecode and returns an executable

Inputs {#scripts-writeJS-inputs}

name

: 1. Function argument

attrs

: 2. Function argument

content

: 3. Function argument

Examples {#scripts-writeJS-examples}

:::{.example}

pkgs.writers.writeJS usage example

writeJS "example" { libraries = [ pkgs.uglify-js ]; } ''
  var UglifyJS = require("uglify-js");
  var code = "function add(first, second) { return first + second; }";
  var result = UglifyJS.minify(code);
  console.log(result.code);
''

:::

writers.scripts.writeJSBin {#function-library-lib.writers.scripts.writeJSBin}

writeJSBin takes the same arguments as writeJS but outputs a directory (like writeScriptBin)

writers.scripts.writePerl {#function-library-lib.writers.scripts.writePerl}

writePerl takes a name an attributeset with libraries and some perl sourcecode and returns an executable

Examples {#scripts-writePerl-examples}

:::{.example}

pkgs.writers.writePerl usage example

writePerl "example" { libraries = [ pkgs.perlPackages.boolean ]; } ''
  use boolean;
  print "Howdy!\n" if true;
''

:::

writers.scripts.writePerlBin {#function-library-lib.writers.scripts.writePerlBin}

writePerlBin takes the same arguments as writePerl but outputs a directory (like writeScriptBin)

writers.scripts.makePythonWriter {#function-library-lib.writers.scripts.makePythonWriter}

makePythonWriter takes python and compatible pythonPackages and produces python script writer, which validates the script with flake8 at build time. If any libraries are specified, python.withPackages is used as interpreter, otherwise the "bare" python is used.

Inputs {#scripts-makePythonWriter-inputs}

python

: 1. Function argument

pythonPackages

: 2. Function argument

buildPythonPackages

: 3. Function argument

name

: 4. Function argument

attrs

: 5. Function argument

writers.scripts.writePyPy2 {#function-library-lib.writers.scripts.writePyPy2}

writePyPy2 takes a name an attributeset with libraries and some pypy2 sourcecode and returns an executable

Examples {#scripts-writePyPy2-examples}

:::{.example}

pkgs.writers.writePyPy2 usage example

writePyPy2 "test_pypy2" { libraries = [ pkgs.pypy2Packages.enum ]; } ''
  from enum import Enum

  class Test(Enum):
      a = "success"

  print Test.a
''

:::

writers.scripts.writePyPy2Bin {#function-library-lib.writers.scripts.writePyPy2Bin}

writePyPy2Bin takes the same arguments as writePyPy2 but outputs a directory (like writeScriptBin)

writers.scripts.writePython3 {#function-library-lib.writers.scripts.writePython3}

writePython3 takes a name an attributeset with libraries and some python3 sourcecode and returns an executable

Examples {#scripts-writePython3-examples}

:::{.example}

pkgs.writers.writePython3 usage example

writePython3 "test_python3" { libraries = [ pkgs.python3Packages.pyyaml ]; } ''
  import yaml

  y = yaml.safe_load("""
    - test: success
  """)
  print(y[0]['test'])
''

:::

writers.scripts.writePyPy3 {#function-library-lib.writers.scripts.writePyPy3}

writePyPy3 takes a name an attributeset with libraries and some pypy3 sourcecode and returns an executable

Examples {#scripts-writePyPy3-examples}

:::{.example}

pkgs.writers.writePyPy3 usage example

writePyPy3 "test_pypy3" { libraries = [ pkgs.pypy3Packages.pyyaml ]; } ''
  import yaml

  y = yaml.safe_load("""
    - test: success
  """)
  print(y[0]['test'])
''

:::

writers.scripts.writePyPy3Bin {#function-library-lib.writers.scripts.writePyPy3Bin}

writePyPy3Bin takes the same arguments as writePyPy3 but outputs a directory (like writeScriptBin)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment