How to install software that does not exist in nixpkgs?

I am currently struggling to understand how I would install software when there is no existing package in nixpkgs and make this available to users path.

Based on the “Your topic is similar to…” suggestion, this one seemed partially relevant:

  1. Use an overlay [1]

However, seems this would assume the package is already defined/available in nixpkgs.

The particular piece of software I am trying to install is svg-term-cli [2]. Since it’s published to npm [3], one can invoke:

npm install -g svg-term-cli

However, I don’t want to install node or npm directly on my machine and bypass the nix-store. I would prefer to manage this via nix. I may have found a similar StackOverflow question and answer [4], but I am not able to adapt it to npm.

I used nix repl -f '<nixpkgs>', however not able to locate this specific package:

$ nix repl -f '<nixpkgs>'
nix-repl> pkgs.nodejs.pkgs.svg-term-cli
error:
       … while evaluating the attribute 'nodejs.pkgs.svg-term-cli'
         at /nix/store/9cdyyswz19r66knbyscl7l42k69vhbib-source/pkgs/development/web/nodejs/nodejs.nix:317:7:
          316|
          317|       passthru.pkgs = callPackage ../../node-packages/default.nix {
             |       ^
          318|         nodejs = self;

       error: attribute 'svg-term-cli' missing
       at «string»:1:1:
            1| pkgs.nodejs.pkgs.svg-term-cli
             | ^
nix-repl> pkgs.nodePackages_latest.svg-term-cli
error:
       … while evaluating the attribute 'nodePackages_latest.svg-term-cli'
         at /nix/store/9cdyyswz19r66knbyscl7l42k69vhbib-source/pkgs/top-level/all-packages.nix:3614:3:
         3613|
         3614|   nodePackages_latest = dontRecurseIntoAttrs nodejs_latest.pkgs;
             |   ^
         3615|

       error: attribute 'svg-term-cli' missing
       at «string»:1:1:
            1| pkgs.nodePackages_latest.svg-term-cli
             | ^
nix-repl> pkgs.nodePackages.svg-term-cli
error:
       … while evaluating the attribute 'nodePackages.svg-term-cli'
         at /nix/store/9cdyyswz19r66knbyscl7l42k69vhbib-source/pkgs/top-level/all-packages.nix:3616:3:
         3615|
         3616|   nodePackages = dontRecurseIntoAttrs nodejs.pkgs;
             |   ^
         3617|

       error: attribute 'svg-term-cli' missing
       at «string»:1:1:
            1| pkgs.nodePackages.svg-term-cli
             | ^

My expectations:

  1. build project from source with instructions defined in nix
  2. binary of project available in users PATH after sudo darwin-rebuild switch --flake ...
  3. No need to install/manage nodejs and npm outside of nix

Would appreciate any help here, even if it’s for the general use case (ie, not using npm but rather building a project from source and making it available in path.

[1] How to install version of a package that is newer then in nixpkgs (2021-12-06)

[2] GitHub - marionebl/svg-term-cli: Share terminal sessions via SVG and CSS

[3] svg-term-cli - npm

[4] https://stackoverflow.com/questions/55068279/what-is-the-recommended-way-to-install-packages-not-in-nixpkgs-pkgs-top-level-a

Write a nix expression in a file (let’s say foobar.nix) and callPackage it (add (pkgs.callPackage ./relative/path/to/foobar.nix { }) to some package list).

See:

2 Likes

I will add that this is really easy to package, there are no weird binary wrappers or anything of the sort. The repo uses yarn v1 and you can literally fill out the example from the yarn section of the docs linked by @waffle8946, nix-build your-file.nix and iterate until you have the two hashes (src/deps). nix-build will kick out the path once it is built and you then should be able to run it!

/nix/store/bfl03nkms9ny1x15gkr4h2ydw52kvwvy-svg-term-cli-2.1.1/bin/svg-term --help

  Share terminal sessions as razor-sharp animated SVG everywhere

  Usage
    $ svg-term [options]

  Options
    --at            timestamp of frame to render in ms [number]
    --cast          asciinema cast id to download [string], required if no stdin provided [string]
    --command       command to record [string]
    --from          lower range of timeline to render in ms [number]
    --height        height in lines [number]
    --help          print this help [boolean]
    --in            json file to use as input [string]
    --no-cursor     disable cursor rendering [boolean]
    --no-optimize   disable svgo optimization [boolean]
    --out           output file, emits to stdout if omitted, [string]
    --padding       distance between text and image bounds, [number]
    --padding-x     distance between text and image bounds on x axis [number]
    --padding-y     distance between text and image bounds on y axis [number]
    --profile       terminal profile file to use, requires --term [string]
    --term          terminal profile format [iterm2, xrdb, xresources, terminator, konsole, terminal, remmina, termite, tilda, xcfe], requires --profile [string]
    --to            upper range of timeline to render in ms [number]
    --width         width in columns [number]
    --window        render with window decorations [boolean]

  Examples
    $ cat rec.json | svg-term
    $ svg-term --cast 113643
    $ svg-term --cast 113643 --out examples/parrot.svg
1 Like

Thank you, @waffle8946 @bme

I didn’t get the normal e-mail notification, but after looking back at your answers and provided documentation. I was able to get it installed without relying on nixpkgs.

As @bme indicated, it was dead simple to get this installed since reference manual [1] gave a template for yarn v1 projects. This is what worked for me in the case of svg-term-cli [2]:

# modules/pkg/svg-term-cli.nix
{
  lib,
  stdenv,
  fetchFromGitHub,
  fetchYarnDeps,
  yarnConfigHook,
  yarnBuildHook,
  yarnInstallHook,
  nodejs,
}:
stdenv.mkDerivation (finalAttrs: {
  pname = "svg-term-cli";
  version = "2.1.1";
  src = fetchFromGitHub {
    owner = "marionebl";
    repo = "svg-term-cli";
    rev = "v${finalAttrs.version}";
    hash = "sha256-sB4/SM48UmqaYKj6kzfjzITroL0l/QL4Gg5GSrQ+pdk=";
  };
  yarnOfflineCache = fetchYarnDeps {
    yarnLock = finalAttrs.src + "/yarn.lock";
    hash = "sha256-4Q1NP3VhnACcrZ1XUFPtgSlk1Eh8Kp02rOgijoRJFcI=";
  };
  nativeBuildInputs = [
    yarnConfigHook
    yarnBuildHook
    yarnInstallHook
    nodejs
  ];
  meta = {

  };
})
# modules/pkgs.nix
{ pkgs, ... }:
let
  custom = with pkgs; [
    (callPackage ./pkg/svg-term-cli.nix { })
  ];
  ...
in
{
  home = {
    packages = custom ++ ...;
  };
}
# modules/default.nix
{ ... }:
let
  modules = [
    ...
    ./pkgs.nix
    ...
  ];
in
{
  imports = modules;
  ...
}

Side notes/questions:

  • I did have to rebuild my flake a couple of times to get the sha256-... hashes above, but is there a way to determine this beforehand without having to build? Maybe upstream has to provide this? Or are these hashes unique to the system (ie, different hash for macOS vs Windows vs Linux)?
$ sudo darwin-rebuild switch --flake /path/to/flake/nix --show-trace
building the system configuration...
warning: found empty hash, assuming 'sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='
evaluation warning: lib.literalExample is deprecated, use lib.literalExpression instead, or use lib.literalMD for a non-Nix description.
error: hash mismatch in fixed-output derivation '/nix/store/prglvl20ry0mpnv7bkfcs2rpy0hbp2k7-source.drv':
         specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
            got:    sha256-sB4/SM48UmqaYKj6kzfjzITroL0l/QL4Gg5GSrQ+pdk=
...
$ sudo darwin-rebuild switch --flake /path/to/flake/nix --show-trace
building the system configuration...
evaluation warning: lib.literalExample is deprecated, use lib.literalExpression instead, or use lib.literalMD for a non-Nix description.
error: hash mismatch in fixed-output derivation '/nix/store/6y9gg6shbcpz5f6divp48w1k1jy8hsgb-offline.drv':
         specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
            got:    sha256-4Q1NP3VhnACcrZ1XUFPtgSlk1Eh8Kp02rOgijoRJFcI=
...

[1] Nixpkgs Reference Manual
[2] svg-term-cli/yarn.lock at fa98a053ce8d0549410778d4d04b51f1facf965f · marionebl/svg-term-cli · GitHub

Perhaps you should think about submitting your first PR against NixOS/nixpkgs so that it would be available for any users using Nix :wink:

Hi @drupol - I considered this but seems the upstream has been abandoned (last commit was ~6 yrs ago). I don’t think it would meet nixpkgs standards [1] and I quite frankly don’t have time to get it up to those standards by myself.

Might consider it in future as a side project and learning experience.

[1] https://github.com/NixOS/nixpkgs/blob/c19390a96d5ad267c59b781d3cc3696405b79264/pkgs/README.md#quick-start-to-adding-a-package

Fair enough, I don’t believe it worth adding in nixpkgs then.

Not really. Simple sources can use nix-prefetch-url, if you are using something like npins you can have it fetch sources then just refer directly its imported expression. For something like yarnFetchDeps, it really does need to be calculated. You can see my adventures with this question and yarn here. There is of course nix-update which is mentioned in that thread.

EDIT: @malloc pkgs.prefetch-yarn-deps is totally a thing

1 Like