A few days ago, version 1.9 of the Nix package manager was released. From the release notes:

nix-shell can now be used as a #!-interpreter. This allows you to write scripts that dynamically fetch their own dependencies.

They followed with an example that used GHC’s runhaskell to execute Haskell code using libraries that had been specified in the shebang line. Unfortunately, this specific example doesn’t work, as it isn’t sufficient information for Haskell to find the Network.HTTP library. But this notwithstanding, it is still an interesting change that I have found useful.

Why?

First, why would you use this? Several reasons. As quoted above, your scripts can auto-fetch their own dependencies. This makes sharing and deploying scripts to other Nix-based systems easy. No having to remember exactly everything that is needed. The script will fetch and install whatever it needs. If the system already has the package installed, Nix will just use that.

Second, I use this (as is one of my big motivations for Nix in general) to isolate things. I have the minimum set of packages installed to keep my system running and support the applications I run regularly. Then particularly for project specific scripts – things not useful outside the context of the project, or may have dependencies separate from what the system in general might use – I like using nix-shell scripts. I don’t have to install all of the libraries (gems, npm packages, etc) needed and clutter up my system or $HOME.

Using nix-shell in a Shebang Line

To use it, start your scripts with two lines similar to this:

#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p python3 python34Packages.pygobject3 libnotify gobjectIntrospection gdk_pixbuf

This is a little different than some other shebang lines you might have seen before. First, why use /usr/bin/env instead of calling nix-shell directly? As explained in the answers to this Unix StackExchange question, this allows the script to be more portable. On NixOS systems, you could generally reference /run/current-system/sw/bin/nix-shell as the nix-shell path. In fact, in previous edits of this post I used that in some of my examples. But if you wanted to share this with a system that was using Nix on top of another distribution or OS, that wouldn’t work.

Related, the second line is needed to get around a potential limitation (depending on the system you are running on) in the way that interpreted scripts are launched. Quoting the Interpreter scripts paragraphs under the NOTES section of the execve(2) man page:

A maximum line length of 127 characters is allowed for the first line in an interpreter scripts.

The semantics of the optional-arg argument of an interpreter script vary across implementations. On Linux, the entire string following the interpreter name is passed as a single argument to the interpreter, and this string can include white space. However, behavior differs on some other systems. Some systems use the first white space to terminate optional-arg. On some systems, an interpreter script can have multiple arguments, and white spaces in optional-arg are used to delimit the arguments.

So, the second line allows passing multiple arguments to nix-shell, allowing for spaces in those arguments, and dealing with a potential line-length limit.

Examples

The -i parameter to nix-shell tells it which interpreter to use when executing the script. Often, it is from one of the dependencies, such as in the above example. The -p parameter gives one or more dependencies to be used. After the above lines follows the script (shamelessly borrowed from the ArchWiki):

#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p python3 python34Packages.pygobject3 libnotify gobjectIntrospection gdk_pixbuf

from gi.repository import Notify
Notify.init("Hello world")
Hello=Notify.Notification.new("Hello world","This is an example notification.","dialog-information")
Hello.show()

But its usefulness isn’t limited to just writing scripts interpreted by one of the declared dependencies. I needed to write a wrapper for some NodeJS scripts I had installed in the node_modules directory of a project I am working on. I didn’t want Node installed globally, so I did this:

#! /usr/bin/env nix-shell
#! nix-shell -i bash -p nodejs

readonly BIN_DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly CMD="$(basename ${BASH_SOURCE[0]/%-wrapper/})"

"${BIN_DIR}"/"${CMD}" "$@"

I simply made a symlink for each program in my node_modules/.bin directory to this file, with the name program-wrapper, for example, tern-wrapper to wrap tern. Notice my script doesn’t directly call nodejs, though the underlying script it calls does.

I wrote the following script to render this document as I was writing it to check the way it looked in HTML:

#! /usr/bin/env nix-shell
#! nix-shell -i bash -p inotifyTools pandoc

readonly FILE="$*"

if [ $# -lt 1 ]; then
    echo "Usage:  ${0} MARKDOWN_FILE" 2>&1
    echo "" 2>&1
    echo "MARKDOWN_FILE must exist before launching." 2>&1
    exit 1
fi

if [ ! -e "${FILE}" ]; then
    echo "${FILE} doesn't yet exist, create it before launching!" 2>&1
    exit 1
fi

# Assume the extension is .md
readonly OUTPUT=$(basename "${FILE}" ".md").html

echo "Press Control-C to quit watching for changes on ${FILE}."
while true; do
    inotifywait -q -e modify "${FILE}" &&
        echo "Updating HTML for ${FILE}" &&
        pandoc -s -f markdown -t html -o "${OUTPUT}" "${FILE}"
done

One last example, where I couldn’t use nix-shell in a shebang line. I was playing with Hakyll. After you use haykll-init to generate your project structure, all work is done by compiling your own code (in this case, a site.hs that has an accompanying cabal file. Since something similar to the example from the release notes didn’t work, I tried the following, a variant of what I’ve used in .nix files.

#! /usr/bin/env nix-shell
#! nix-shell --pure -i bash -p 'pkgs.haskellPackages.ghcWithPackages (pkgs: with pkgs; [ hakyll cabal-install ])'

cabal run $@

But nix-shell didn’t like this:

nafai@shedemei:~/Documents/blog/hakyll/technically
$ ./site-wrapper 
error: syntax error, unexpected ')', at (string):1:66

So I had to just make this one a regular shell script:

#! /usr/bin/env bash

nix-shell --pure \
          -p "pkgs.haskellPackages.ghcWithPackages (pkgs: with pkgs; [ hakyll cabal-install ])" \
          --run "cabal run $@"

Anyway, just in these last few days I’ve found interesting ways to use this new capability. I hope this gives some examples of how it may be used. I plan on writing more posts about other ways I have used this and other useful ways I have used Nix tools. I welcome any feedback from more experienced Nix users (or comments in general about my scripting, I’m a little out of practice).

Updates

On June 22, 2015, I updated the post to expand the explanation of why this might be used, why /usr/bin/env was used along with a second script line, and cleaned up and made my examples more consistent.

Sometimes, I forget I am not like the most of the world. Sometimes, I forget just how much our reality shapes our vision.

A few vignettes:

My sister Sharalyn recently reminded me of this story. We were young. I was perhaps 7, she would have been 4. By that time she was already taller than me. Our Dad is a truck driver, and there were always trailers parked in our yard. I would run underneath the front of the flat-bed trailers, instead of going around them, to get out to the mailbox by the road. This one day, Sharalyn followed me. Unfortunately, she was met with a big surprise.

Underneath the front of the trailer is a little metal rod called the kingpin. It was what hooks the trailer up to the truck. These are lubed with grease so they can turn. It sticks down about six inches or so below the rest of the trailer.

I was short enough to go right underneath. It didn’t occur to either me or my sister, at that age, that she could not. She ended up getting grease all over in her hair and went inside really unhappy. She recalls it as the first time it really clicked to her that she and I were different.

This morning, I was watching the latest Mormon Messages video on Youtube. I was still in bed myself, still hooked up to my dialysis machine. As I watched the mother in this video needing to get out of bed to go take care of her children, my natural thought was, “well, she needs to get unhooked first, before she can get up!” Of course, immediately, I realized that I was projecting my circumstance onto her. It was like having to all over again realize, hey, I’m different.

I remember a year or so ago watching a movie. Again, someone was just waking up and ready to get out of bed. They sat up and turned to the side of their bed. I remember thinking it was so odd that their feet touched the ground. My experience has always been no matter how high something is that I’m sitting on, my feet don’t reach the ground. In my mind, I took for granted the fact that not everyone is like this.

One last slightly different story. I was still at university, probably about 24-25. I was walking across campus by one of those buildings that was all glass. I glanced over as I was walking, and got a glimpse of my whole self. I remember doing a double-take. Was this really me? It was like I didn’t identify with the body I had lived my whole life in.

§

I’ve always teetered the thin line between recognizing how myself or my life is different than most or thinking I’m just like everyone else (or they are just like me). As a child, I think I knew I wasn’t like my brother or sister. But, looking back, I don’t think it really clicked I was different. My experience this morning of projecting my normalcy of my dialysis procedure onto this women in the video shows how that continues. We each live in our reality, and it colors the way we see the world. A friend wrote on Facebook this morning how her life was so different from many of her friends, as they were writing about potty training or helping their children with homework, and she is single and her biggest worries are related to her responsibilities at work or news of the world.

Sometimes, whether it is a difference like being single instead of married and a parent, or dealing with chronic illness or not, or being a different race, or religion, or gender or whatever, you might constantly have to realize that difference in experience all over again. And, sometimes, that reminder carries with it a judgment (whether perceived or real) on the value of the difference.

I know that my experience is not like everyone else’s. Sometimes, perhaps there’s a twinge of sadness when I am reminded of that. And I know that sometimes others may experience something similar. A conversation may remind them of something they lack that they desire. Or how simply they are different. I know I have to be sensitive to others. And to remember, my views are through the lens of my experience, no matter how “normal” or “non-normal” it is.

This is based on something I wrote back in February 2005, while taking a New Testament Class at the Austin LDS Institute of Religion, after I had read Acts 3:1-8.

I find the story of the lame man healed by Peter and John at the temple gate to be a beautiful metaphor for repentance and the other ways in which the Savior changes our lives.

Just like this man, we each are “lame from birth” (Acts 3:2). Call it what you will — our sinful nature, the natural man, or even more simply this veil of forgetfulness and the separation from God we experience here in our mortal lives. Each of us, like this man, are beckoned to look to, and listen to, our prophets and other church leaders. Because, ultimately is it not his voice that is calling us (see Mosiah 26:21, Mosiah 5:12, D & C 18:33-36) because “whether by mine own voice or by the voice of my servants, it is the same” (D & C 1:38).

Importantly, at this time, this man was ready to receive something into his life that he could not provide for himself. In this expectation, he looked to the apostles. He was humble. He could not overcome his current situation on his own. He was much like the poor of the Zoramites, who looked to Alma to know how to worship since they were cast out of their synagogues because of their poverty. Alma saw that they were “in a preparation to hear the word.” (Alma 32:6) But, remember, one does not have to be compelled by being in a situation as this man or the Zoramites to receive this gift (see Alma 32:16).

Now, with the man looking to our Savior (because he was looking at our Savior’s servants), he is invited to do something that only the name and power of Christ can do and give: “rise up and walk” (Acts 3:6). Only Christ has power to bid us rise up and walk out of our condition of being “lame from birth”; only he can deliver us from this weak state (Mosiah 23:23).

“Arise and walk!”  Isn’t that essentially His invitation to us (3 Nephi 9:13)? When Christ invited the Nephites to gain a personal testimony of his atonement and resurrection, didn’t he say “arise and come forth” (3 Nephi 11:14)? He also said nearly the same to the people of Alma, beckoning for them to arise, walk, and receiving strength to bear their burdens (Mosiah 24:13-15).

It is obvious that the man lame from birth heeded this command. But, the man did receive more than the command to rise up and walk. Peter extended his hand and lifted him up — it was then that his bones and feet received the needed strength. Think of Nephi’s faith in the ability to keep the commandments (1 Nephi 3:7). The man was commanded to rise and Peter’s outstretched hand was the way for the command to be heeded. It is true, our Savior sometimes sends help that is not mortal (see 2 Kings 6:16-17, D & C 84:88); but often this help is sent through another mortal. Can we not look at the example of Peter and help those who are need (See D & C 81:5)?

It was after he exercised faith (he listened, he heeded the Lord’s command, and then took Peter’s hand) that he received his blessing, his strength.

He arose! He leaped! He walked! A miracle had been performed. A man once lame could now leap and walk! So must we also arise and walk. We must reach out to the help the Savior offers to us. We find when we do this, we receive strength and ability. He does for us what we could not do; lives are changed, sins are forgiven, hearts softened. We awoke. We abandoned sin. We have place for God in our hearts (2 Nephi 4:28).

Now this change had taken place, where did Christ’s servants lead the man? To the temple. We follow our leaders. Repentance and change of heart comes through the power of Christ. We have risen, we are walking his path. Now, let us enter the temple. Let us enter into the covenants to be had there. Let us follow the Savior (through his servants) to the temple.

Once there, once in those covenants, what do we do? Do as the man did. Continue in those things our Savior’s power provided. We “leap”. We “walk”. We retain a remission of our sins (Mosiah 4:11-12, Alma 5:26).

Also, very importantly, we praise and thank God for what he has done. This is what Nephi did (2 Nephi4:20,30). This is the way we receive blessings, “with a thankful heart in all things” (D & C 62:7). We can then “stand as a witness” (Mosiah 24:14) for his great blessings and power.

Indeed, let us “rise up and walk!”

Postscript: This story also has special meaning to me. The way this man is described as his feet and ankle bones receiving strength sounds like it could be a description of one of the conditions I was born with, valgus of the ankles. I was 22 months old, and not yet walking. My parents finally convinced the doctors that something was wrong. After performing x-rays, they discovered I had this condition. I was fitted for braces (AFOs or “ankle foot orthosis”). The doctors told my Mom to put me down so I could walk. She wasn’t sure I could, because I had not yet walked. She sat me down. I didn’t walk. My first steps were running across the room.

The Savior’s grace is like those first braces that enabled me to run and the braces I continue to wear today. It enables you to run. I am grateful for the Savior’s grace.

I may be going blind
and the darkness encroaching from all sides.
But at least with clarity
now I see all directly in front of me
No longer the periphery is important
this I must finally accept
When looking straight forward
I see me, reflected right back.
In this mirror, I see the hurt and the pain and the exhaustion
all reflected so clearly in what is before me.
But also sometimes the clouds move
and the sun shines, revealing what is inside.
That glory, those heaven-sent photons
hit my heart with a whisper
I open my heart to finally hear
and I am lifted to that higher place
Elevated, I see that which is reflected back,
that right in front of me.
Different from before is what my dim eyes see
higher, noble, good, beautiful.
Suddenly, as if I’ve found just one last breath,
the exhaustion sets in.
My vision falls
but I hold it in my heart, a little spark.
Even when it feels I cannot rise to those lofty heights of grandeur
no longer one day I will see
So clearly, the light I see right in front of me
won’t be reflected back to me, but reality.

It often takes a long time to learn lessons and let them sink in. Sometimes we rebel against what we know that life is saying to us. But, sometimes, you get to a point where you can no longer ignore that which is front of you.

Of course, this is also due to a lifetime of things, but in recent months, my mind and heart have finally started opening up to the things I need to know and do. I never imagined, and still waver at times, that I would be able to reach the point I am or get on the path that I am. But, I realize all things will be provided. I just have to seek for those things.

Indeed, this seeking is a lesson that I am learning. Most importantly is what we seek. When I desired peace and joy and strength, where was I looking? I was looking at where I had none. But by bringing my focus repeatedly back to what I truly want and the conditions that I need to have those things, then it will come about.

In and of itself, this is a lesson for me; there is so much beyond my reach. I naturally think to get what I desire, I have to bring it to myself. But time and again, I have been taught what is most important is having the want first. And, then do what is in my power to bring about the circumstances needed for what I desire. If my desire is true and right, in those circumstances, I will see the blessings flourish.

That action, no matter how small, is a critical part. As I have learned more of neuroscience, I realize our brains follow a simple reward-driven focus. The brain will naturally seek to have that release of neurochemicals that make it feel good. An oft used phrase is “What fires together, wires together.” If a certain action brings reward, the brain will form new neural connections to reinforce that. This is why habit — and in its extreme form, addiction — is so powerful. Your brain knows that certain things bring the desired reward, and it will bring all to bring that about.

Luckily, we as humans can recognize this and use it to craft those “right conditions” for whatever we want. What are the things that bring them about? I have once again embraced a long-lost habit of writing and journaling. I know, without a doubt, that it has been instrumental in the healing in all facets of my life that I have experienced in these last six months. When I forget what has worked in the past and let go, of course I don’t see the life I want. But, in retrospect, consistently the happiest and most authentic parts of my life have been when I have been writing. I remember that, and the other little things I know have helped. I no longer do them because I “have to”, but because just as sure as I need my medication to keep my body alive, I need writing and other activities to stay alive emotionally and spiritually.

This brings me to perhaps the key lesson I’ve learned. To remember. Spencer W. Kimball taught that “remember” was the most important word in the English language. Jesus Christ told his disciples that when sending them the Holy Ghost for comfort after he was gone, the Holy Ghost would bring all things to their remembrance. We cannot forget. What fires together, wires together. Neural pathways get formed. If we remember the blessings of our lives and what has worked in the past, what those things were associated with will work for you. It’s fundamental. Also, I have to remember what that I’ve been taught over and over that these things do not work if I don’t remember what has been taught to me as the order of love. I can’t do anything without first receiving the love of God and putting Him first in my life. It is only with his help that I can then show the love and self-care for myself, to have my own needs met. With my needs met, I can then show and share love with others.

I’m still reminding myself of these things, every day and sometimes every hour. I’ve had to go back to first principles over and over in recent times to learn them. As I remember them, I also feel the nudge and the muse to not just keep it inside. I need to write these things. I will be exploring these ideas in greater detail in later blog posts in the coming weeks.