Build, cache, and run possibly compiled scripts with dependencies using the Nix package manager
Haskell
52
381 commits
updated Aug 20, 2026
[[file:Changelog.org][Changelog]].
* Magix
Build, cache, and run possibly compiled scripts with dependencies using the [[https://nixos.org/][Nix
package manager]].
- Magix is simple and stupid.
- Magix is a tiny wrapper around =nix-build=.
- Magix uses Nix expression templates, and so, is easy to understand, modify,
and enhance.
- Magix is heavily tested (only unit tests at the moment, but please drop a pull
request).
* Supported languages
** Bash
#+name: BashExample
#+begin_src sh :exports code
#!/usr/bin/env magix
#!magix bash
#!packages jq
jq --help
#+end_src
[[file:src/Magix/Language/Bash/Template.nix][Bash Nix expression template]].
** Haskell
#+name: HaskellExample
#+begin_src haskell :session ghci :exports code :results none
#!/usr/bin/env magix
#!magix haskell
#!ghcFlags -threaded
#!haskellPackages bytestring
{-# LANGUAGE OverloadedStrings #-}
import Data.ByteString qualified as BS
main :: IO ()
main = BS.putStr "Hello, World!\n"
#+end_src
[[file:src/Magix/Language/Haskell/Template.nix][Haskell Nix expression template]].
** Python
#+name: PythonExample
#+begin_src python :exports code :results none
#!/usr/bin/env magix
#!magix python
#!pythonPackages numpy
from numpy import array
xs = array([1,2,3])
print(xs)
#+end_src
[[file:src/Magix/Language/Python/Template.nix][Python Nix expression template]].
* Try
Try Magix without installation on a Bash script called [[file:test-scripts/bash/args][=args=]]
#+name: Try
#+begin_src sh :exports both :results verbatim
wget https://github.com/dschrempf/magix/raw/refs/heads/main/test-scripts/bash/args
nix run github:dschrempf/magix#magix -- args one two three -h
#+end_src
#+RESULTS: Try
: Command basename is: args
: Command line arguments are: one two three -h
* Get help
#+name: Help
#+begin_src sh :exports both :results verbatim
magix -h
#+end_src
#+RESULTS: Help
#+begin_example
Usage: magix [-v|--verbose] [-f|--force-build] [-c|--cache-path CACHE_PATH]
[-n|--nixpkgs-path NIXPKGS_PATH] SCRIPT_FILE_PATH [SCRIPT_ARGS]
Build, cache, and run possibly compiled scripts with dependencies using the
Nix package manager
Available options:
-h,--help Show this help text
-v,--verbose Print debug messages
-f,--force-build Force build, even when cached build exists
-c,--cache-path CACHE_PATH
Path of cache directory to use for builds (default:
'$XDG_CACHE_HOME/magix')
-n,--nixpkgs-path NIXPKGS_PATH
Path of Nixpkgs repository to use (default: extracted
from '$NIX_PATH')
SCRIPT_FILE_PATH File path of script to build, cache and run
SCRIPT_ARGS Arguments passed on to the script
#+end_example
* New languages
We have designed Magix so that implementing new languages is straightforward. In
particular:
- Change and add modules only within the =src/Magix/Language/*= namespace.
- Add language-specific tests to =test/Magix/Language/*=.
* Next steps
- Property-based testing (e.g., generate arbitrary directives or even scripts).
When creating arbitrary directives, one could test if the resulting
Nix expressions are syntactically correct.
- We create random caches and hashes during tests. We could write an Arbitrary
instance for =Config= to simplify this process.
* Notes about performance
I have performed basic benchmarks and have recorded some profiles. When a script
is cached, *Magix has a runtime cost of around 20ms*.
* Similar tools that I know of
- [[https://github.com/bennofs/nix-script][bennofs/nix-script]]: Does not pre-compile scripts, does not cache compilations;
however, Haskell code base and complexity seems to be much smaller.
- [[https://github.com/BrianHicks/nix-script][BrianHicks/nix-script]]: Magix was heavily inspired by [[https://github.com/BrianHicks/nix-script][BrianHicks/nix-script]],
which [[https://github.com/dschrempf/nix-script][I also maintain]]. However, my Rust is a bit rusty, and I wanted a simpler
solution.
I want =magix= to be a *simple and fast solution* that just works. If you are
looking for a wrapper with more extras, try the [[https://github.com/NixOS/nix][Nix package manager ;-)]].
Not written in Markdown, so it's shown here as plain text — view it formatted on GitHub.
Haskell
92.2%
Nix
5.2%
Shell
2.6%
Build, cache, and run possibly compiled scripts with dependencies using the Nix package manager
Haskell
52
381 commits
updated Aug 20, 2026
[[file:Changelog.org][Changelog]].
* Magix
Build, cache, and run possibly compiled scripts with dependencies using the [[https://nixos.org/][Nix
package manager]].
- Magix is simple and stupid.
- Magix is a tiny wrapper around =nix-build=.
- Magix uses Nix expression templates, and so, is easy to understand, modify,
and enhance.
- Magix is heavily tested (only unit tests at the moment, but please drop a pull
request).
* Supported languages
** Bash
#+name: BashExample
#+begin_src sh :exports code
#!/usr/bin/env magix
#!magix bash
#!packages jq
jq --help
#+end_src
[[file:src/Magix/Language/Bash/Template.nix][Bash Nix expression template]].
** Haskell
#+name: HaskellExample
#+begin_src haskell :session ghci :exports code :results none
#!/usr/bin/env magix
#!magix haskell
#!ghcFlags -threaded
#!haskellPackages bytestring
{-# LANGUAGE OverloadedStrings #-}
import Data.ByteString qualified as BS
main :: IO ()
main = BS.putStr "Hello, World!\n"
#+end_src
[[file:src/Magix/Language/Haskell/Template.nix][Haskell Nix expression template]].
** Python
#+name: PythonExample
#+begin_src python :exports code :results none
#!/usr/bin/env magix
#!magix python
#!pythonPackages numpy
from numpy import array
xs = array([1,2,3])
print(xs)
#+end_src
[[file:src/Magix/Language/Python/Template.nix][Python Nix expression template]].
* Try
Try Magix without installation on a Bash script called [[file:test-scripts/bash/args][=args=]]
#+name: Try
#+begin_src sh :exports both :results verbatim
wget https://github.com/dschrempf/magix/raw/refs/heads/main/test-scripts/bash/args
nix run github:dschrempf/magix#magix -- args one two three -h
#+end_src
#+RESULTS: Try
: Command basename is: args
: Command line arguments are: one two three -h
* Get help
#+name: Help
#+begin_src sh :exports both :results verbatim
magix -h
#+end_src
#+RESULTS: Help
#+begin_example
Usage: magix [-v|--verbose] [-f|--force-build] [-c|--cache-path CACHE_PATH]
[-n|--nixpkgs-path NIXPKGS_PATH] SCRIPT_FILE_PATH [SCRIPT_ARGS]
Build, cache, and run possibly compiled scripts with dependencies using the
Nix package manager
Available options:
-h,--help Show this help text
-v,--verbose Print debug messages
-f,--force-build Force build, even when cached build exists
-c,--cache-path CACHE_PATH
Path of cache directory to use for builds (default:
'$XDG_CACHE_HOME/magix')
-n,--nixpkgs-path NIXPKGS_PATH
Path of Nixpkgs repository to use (default: extracted
from '$NIX_PATH')
SCRIPT_FILE_PATH File path of script to build, cache and run
SCRIPT_ARGS Arguments passed on to the script
#+end_example
* New languages
We have designed Magix so that implementing new languages is straightforward. In
particular:
- Change and add modules only within the =src/Magix/Language/*= namespace.
- Add language-specific tests to =test/Magix/Language/*=.
* Next steps
- Property-based testing (e.g., generate arbitrary directives or even scripts).
When creating arbitrary directives, one could test if the resulting
Nix expressions are syntactically correct.
- We create random caches and hashes during tests. We could write an Arbitrary
instance for =Config= to simplify this process.
* Notes about performance
I have performed basic benchmarks and have recorded some profiles. When a script
is cached, *Magix has a runtime cost of around 20ms*.
* Similar tools that I know of
- [[https://github.com/bennofs/nix-script][bennofs/nix-script]]: Does not pre-compile scripts, does not cache compilations;
however, Haskell code base and complexity seems to be much smaller.
- [[https://github.com/BrianHicks/nix-script][BrianHicks/nix-script]]: Magix was heavily inspired by [[https://github.com/BrianHicks/nix-script][BrianHicks/nix-script]],
which [[https://github.com/dschrempf/nix-script][I also maintain]]. However, my Rust is a bit rusty, and I wanted a simpler
solution.
I want =magix= to be a *simple and fast solution* that just works. If you are
looking for a wrapper with more extras, try the [[https://github.com/NixOS/nix][Nix package manager ;-)]].
Not written in Markdown, so it's shown here as plain text — view it formatted on GitHub.
Haskell
92.2%
Nix
5.2%
Shell
2.6%