Luminescent Dreams

Remembering Amelia


Tonight, I want to tell you about a dear friend. Someone very important to myself and to my partner, Daria.

Hir name was Amelia. Ze took hir own life late in the night last Tuesday. I found out as soon as I woke up Wednesday morning. A week ago today.

Amelia was gorgeous. Ze was brilliant. Ze sparkled, flirted, brightened spaces, tied innuendo into unexpected sentences, and could talk about advanced mathematics that I cannot begin to understand.

But, honestly, we never talked about advanced math or technology. Amelia was passionate about social justice. Ze came into our community during a chance run-in at a march in solidarity for immigrant’s rights. Late in hir life, ze started campaigning for patient’s rights in mental health. This hyper focus came about from continuous failures in her stays in various psych wards here in Boston. Some of these failures caused significant harm.

Make no mistake. While Amelia may have died at hir own hand, ze was driven to it. Multiple assaults from random men on the street who continue to feel liberty in how they treat women, followed by hospitalizations that dehumanized hir, ignored hir, and in some cases, did significantly more harm.

I miss my friend.

I miss a friendship lost.

I regret the tensions between us, the things we did not have time to heal.


The day we all found out, the morning after Amelia died, seventeen people gathered for an impromptu wake.

Let that sink in. Seventeen people dropped everything to gather, weep, and reminisce, with no advance notice. Queer community is not large, but it is tightly connected and our members are loved. To quote my friend Aria:

Queer culture is grieving as a family no outsider would recognize, a haphazard landslide of lovers & friends. The ones who bring the tequila & gin, the ones who bring the casseroles, the ones who bring the cookies and apologize about the butter, the ones who make a big thai curry

While we can never change what outsiders would see, I want very much to change the definition of “outsider”. While I always live visibly, I have not in the past put much effort into broadcasting that image, and it thus became possible for people ostensibly in my life to completely ignore that which they did not see. But that means that, should I die, there are many people who would have to learn about the full me only through pictures and stories. If they learn at all. Perhaps they would actively ignore.

For now, however, I want to actively try to show what a happy, healthy life outside of the norm of cisgender, heterosexual, monogamy looks like.


For the next ten days, my resistance against fascism is to sit with an enby who has just undergone surgery. The kind of person and surgery that self-proclaimed “decent folk” believe is an abomination worthy of death.

If you are one of them, fuck off.

A Quiet Walk, Interrupted

Ice Flow, 2017-01.web

Yesterday, my friend and I were out walking along the Delaware Canal Towpath in Morissville, Pennsylvania, having a lovely day. Part of the canal is still frozen, and we made a hobby of seeing if we could break the ice using whatever rocks we had to hand. The sound of an ice sheet fracturing is really unique. Not precisely like glass shattering, because the fracture and stresses race down the ice sheet, even if the break only happens in a small area. I lost count of the number of significant rocks that I hurled into the ice that simply got embedded.

We are pretty much minding our own business when an old man walking the other direction starts demanding to know where we’re going “dressed like that” and telling us “you’re not real girls”. He proceeded to hurl invectives after us for long after we could hear him. He even proclaimed just how great it must be to have wealthy parents who will support my “lifestyle”.

When I was twenty, I clawed my way nearly to financial independence to be free of my parents rules. I’ve been on my own ever since. I wanted so much to walk up and tell him precisely how much I get paid for my skills at a job that keeps me in air conditioning. The idea of shaming him into silence was almost overpowering. I am a professional in my field, not even 40, nearly at the top, and I make more money than he likely ever has.

How pathetic. Long after we could no longer hear him, we could see him still yelling at us. He had nothing better to do with his sorry excuse for a life.

It is very difficult to walk away silently. I cannot help but feel that I accomplished nothing. That there is no victory to the high road. But that perhaps there is nothing to be accomplished in my reply.

I so rarely face actual transphobia on the streets. So rarely that I vacillate between being shocked when it happens, and shocked that nobody even looks sidelong at me, even when I’m in a small town. For the rest of our walk, we kept our eyes out. We have no idea what the old man may have done. Perhaps he called the cops on us, as has happened so often to people like us. If he did, they ignored him and we continued the rest of our day unmolested.

Decent Folk

So often, the narrative is that we are a threat to “Decent Folk”. Somehow, trans queer reality is so powerful that all wholesome goodness breaks down around us.

Decent Folk assault people on the street.

Decent Folk poke their noses into other people’s private lives.

Decent Folk remain silent when death camps rise.

Decent Folk vote for a fascist, rapist, traitor because he pedals lies of prosperity.

Decent Folk vote for one who promises more power to those with power.

Decent Folk are so easily duped with fascist lies.



We are the ones who take in those not our kin. Teenagers thrown out of their homes for being gay, lesbian, transgender, bisexual, asexual, intersex, polyamorous. Strangers moving into a city where they can be safer.

If we could, we would walk away from your fucking “decent” culture. We would separate ourselves and build a civilization of our own. We would interact with you only to rescue the queers who emerge amongst you.

But you won’t permit that. You “Decent Folk” have all the power. So fuck you.

Setting up a Custom Nix Channel

Happy Friday the 13th, everyone!

This week has gone extremely well, with me finishing a project for work that will actcually help save lives. Lots of lives. And I for the life of me cannot actually think of any way in which the application can be used to create harm.

At the same time, I’m tuning my tools, and this week, that means my shell.

I’ve been working on switching my shell environment away from being a nix-shell all the time and back to being something more like the config.nix based environment that the Nix maintainers envisioned.

In the midst of this, I decided that it would also be good for me to grab all of the derivations that I’ve been duplicating from one project repository to another, and drop them into a custom nix channel.

I describe all of my development environments in a shell.nix file that I keep with the application that I’m developing. Part of my discpline also involves standardizing on a particular version of my tools, such as Rust-1.33 instead of whatever version of Rust is currently available in the public NixPkgs repository. Until this week, that meant keeping a Rust derivation file in the project repository. That inevitably leadf to me duplicating gthat derivation file (and Node, and other things), across a variety of repositories.

This was probably optional with my work repositories, but the repositories I build for Luminescent Dreams ship with the shell.nix and default.nix, and so have to also ship with the other derivations.

My own custom channel became the obvious solution, but I did not think of it until late last week.

So, while the format is actually very straightforward, I did not find documentation on how to set up the channel repository and for a while did not think of the simplest, most obvious way of finding out the format. So, here I document it all.

You will start out by building a very simple derivation set in a default.nix file:

{ system ? builtins.currentSystem }:
  pkgs = import <nixpkgs> { inherit system; };
  self = in self
in rec {
    rust_1_33_0 = pkgs.callPackage ./pkgs/dev/rust-1.33 {
      inherit pkgs;

    nodejs_9_10_0 = pkgs.callPackage ./pkgs/dev/node9.nix {
      inherit pkgs;

Every element in this set; in this case rust_1_33_0, nodejs_9_10_0, and so forth; will be available in the channel.

Next, make sure you actually define he derivations described here. Errors won’t be detected until somebody who subscribes to the channel actually tries to install something. Obvious errors, like failing to pass a parameter to a derivation, will completely break the channel and are thus easy to find.

Finally, move one directory up from your default.nix, and tar the entire directory:

> ls -l

total <whatever>
drwxr-xr-x 4 savanni staff  128 Sep 12 11:02 nixpkgs

I actually do not know whether the name of the directory matters, but I mimicked the naming convention that I found in the main nixpkgs channels. Tar up the nixpkgs directory, with bz2 compression, to the file nixexprs.tar.bz2:

> tar -cjf nixexprs.tar.bz2 nixpkgs

Finally, upload nixpkgs.tar.bz2 to a public location. This file alone is all it takes to make a channel.

To use the channel, add it to your nix channel list, but be sure to include the exact url. For instance, to get my Luminescent Dreams channel, this is your command:

nix-channel --add luminescent-dreams

My Channel

I am now running my own custom channel for Luminescent Dreams, in which I distribute both the exact versions of the tools that I use and the software that I develop. As of today, that includes:

  • rust-1.33.0
  • nodejs-9.10.0
  • nodejs-10.15.3
  • ansible-2.7.4
  • certbot-0.19.0
  • packer-1.1.3
  • terraform-0.12.2
  • vault-1.0.1
  • fitnesstrax-0.0.1
  • fitnesstrax-0.0.2

Soon I’ll add orizentic, palimpsest, and digikam-export to the channel.


Brilliant Sunset, 2019-01

We had a spectacular sunset in the Boston area last night.

Tech Chaos for September 20th, 2019

That's No Moon!, 2019-07

TGIF, and welcome back, y’all!

I am currently struggling with some pretty severe mental health issues, so about the only thing I have the energy to do is write today. Worst part of this mental health issue is that it is mostly about anxiety, and fearing the worst in an upcoming event. But I cannot do anything to put the anxiety aside, and I cannot do anything to bring the event on faster so I can find out the results, so… sucks to be me at the moment.

I will try to keep it coherent today.

Fitnesstrax 0.0.3

Over the course of the weekend, I released Fitnesstrax 0.0.3 on my nix channel. Unfortunately, even though I thought I got this squared away last week, the channel actually does not work as a channel. You can instead use the channel by cloning the repository and including it like so:

  ld = import /Users/savanni/src/luminescent-dreams/luminescent-dreams-nixpkgs/nixpkgs/default.nix {};`

This release involves a rather significant overhaul of the edit interface in order to accommodate more workout types.

In order to add Pushups and Situps (part of my regular workout routine), and soon to also add things like Tai Chi that are based solely on the amount of time that I spend practicing, I really needed to look at the user interface for the application. When I started, I was thinking that it would be cool to just have a section for Time/Distance workouts and another section for Set/Rep workouts, and logically another section for Time-only workouts. And this is obviously absurd. People want to add workouts and get a relevant user interface for each.

Much of my efforts over the weekend involved overhauling the interface. Now, each record can be edited separately. Workouts get added from a drop-down menu. Workouts get rendered through dynamic dispatch of what workout type is there. You no longer get “sections” for each major workout category, but just get more of a record for the day.

Really, this should have been obvious from the beginning. But, now it is there and I can store all of my pushup and situp workouts in the app that I have been working on for ages.

An irony to this whole thing is that I want to swap the app out for a native application, and that is going to be a huge task. My goal here is to get all of my workout types into a coherent UI with the minimal amount of effort so that I can then really focus on building a native UI.

A New Machine

Speaking of a native UI (bear with me here), I have finally decided that I need to get a new machine. I strongly, strongly prefer to only have to manage one computer, but as a consultant, it is rather difficult to merge my work computer and my personal computer. I use tools such as Nix and Docker to keep my environments from colliding with one another. Unfortunately, not all of my clients are particularly okay with creating truly isolated environments. Also, I recently did work with Ruby, and there was, at the time, a problem with some of the derivations for Ruby gems in Nix. I had to install Ruby with RVM in order to move forward, and for a bit it looked like I had already irrecoverably corrupted my machine.

So, although my new client will be giving me a dedicated computer to work with, I have decided that I really need to have a personal computer that I can keep very well packaged and clean, a work computer that I can regularly wipe and reinstall, and a client computer when the client has more particular needs. In the third case, my work computer may actually go silent for months while I spend my work hours on the client.

In deciding that I need a new machine, I also decided that I really, really, really want to go back to Linux. This actually means that instead of recoding the Fitnesstrax UI for MacOS, and doing the Rust language binding work for the Cocoa libraries, I am instead going to recode for GTK. In some sense, though, this also makes sense. Apple really has fitness tracking cornered on MacOS, and I sincerely doubt that I would get many users there. By contrast, Linux only has the online services, so I expect to get some early users from privacy-minded demographics.

Specs for the new machine: super lightweight laptop, longest battery life I can manage, 16GB of memory, 1TB SSD. Turns out, this is being really hard to find. I have found a customized machine from Lenovo that fits the bill, but shipping time is something like 4 weeks from now. It looks like I can get a machine from System76, but I will have to research. My past experience is that their laptops are rather bulky and have very poor battery life.

React Hooks

While I was reading onboarding documents for my new client, I noticed that they use React Hooks through their code. I knew nothing about them, but I realized that Fitnesstrax already runs the correct version of React to use them. So, I overhauled one of my components. I am actually very pleased with the result. My stateful components remain stateful, but the useState hook hugely reduces the amount of boilerplate code that I have to set up in order to manage component state!

I am unlikely to do anything more with React Hooks in my open source work for the forseeable future since I intend to switch over to GTK work, but it is a new tool that I recommend that everyone looks at.

Licensing and Pulling Power back from Corporate Interests

I have been using a lot of BSD-3 licensed code for a long time, and I have also been distributing my code under the BSD-3 license. But, corporations love this license. Unlike the GPL, it allows them to make products cheaply without providing any benefit back to the open source developer who put their precious time into the software that their projects depend on. Further, I know that in recent years corporations want to see your Github work as a condition for hiring.

I feel that the situation here is very complicated. I want to be able to work on things that bring benefits to individuals. But it is very unlikely that anyone would actually pay me for my open source work. I am most interested in having software, such as Fitnesstrax and Emseries adopted by as many individual users and open source developers as possible, but I also want corporations to either unambiguously hire me or pay me for my work.

Realistically, nobody but me is currently using any of my work. So, let’s set that aside and simply consider class solidarity. Specifically, solidarity with marginalized tech workers who have difficulty getting employed, do not have the time to put into open source work, or who simply do not want to give their free time away to corporations.

The GPL of course comes to mind, but certain black developers that I follow have started evangelizing the Parity and Prosperity licenses and the License Zero method of licensing software for commercial and closed source use. I am trying to begin conversations with folks about what that really turns into and how that would affect my open source development model. I hope to share more thoughts here as soon as I understand.


Last topic: employment.

Recruiters come looking for me on a pretty regular basis, but they pretty much ignore that I’ve specifically requested to never be contacted about Python positions. I have over a decade of Python programming experience, and I categorically hate the ecosystem. I also fail to understand why anyone would not want type guarantees at the time that their program starts running. Tell me: why would you want to have to write extra tests to validate that you are always calling functions correctly? Do you really want to find out about these things when they fail in production? Get real, folks.

I have a really damned good job with Cloud City Development. Great co-workers, management that actually does behave in solidarity with the employees, and a variety of jobs. This includes a job that I did over the last two months to accelarate how countries improve their public health policies! I don’t like our tech platform, but the culture really tips the balance wildly in favor of the company.

I even vaguely think that my managers would secretly been pleased if I had gone on climate strike today instead of having a major anxiety breakdown.

So, if any recuriters read this, know that you have an incredible bar to cross to even get a response from me. And at this time, the bar looks like this:

  • Rust, Typescript, Haskell, Nix
  • Linux-first development environment
  • Combating global climate change, building products that safeguard customer privacy rights, or aiding public health.

As a quick hint: if the product must be connected to the cloud, it does not safeguard customer privacy rights. I don’t care how revolutionary you think you are. My data, especially my health and fitness data, should literally never leave my devices.

And that’s it for this week! I hope to make this a regular column, though perhaps I will have to keep it shorter when I am doing focused work.