Skip to content


Invoking nix run <flake-ref>#<output-name> will actually first look for a <output-name> entry in apps, before looking for a <output-name> entry in packages.

Defining apps entries is useful when a package provides multiple binaries which you want users of your flake to be able to run directly via nix run.

Defining app entries

Each app entry is system-dependent, the key is the output (i.e. the name you will be referring to when using nix run) and the value is an attribute set whose program entry points to the binary to execute:

example - exposing pydoc3 as an app
  # flake.nix,
  description = "nix starter flake pinned to 22.11";

  inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.11"; };

  outputs = { self, nixpkgs }:
      allSystems = [
        "x86_64-linux" # AMD/Intel Linux
        "aarch64-linux" # ARM Linux
        "aarch64-darwin" # ARM macOS

      forAllSystems = fn:
        nixpkgs.lib.genAttrs allSystems
        (system: fn { pkgs = import nixpkgs { inherit system; }; });

    in {
      # used when calling `nix fmt <path/to/flake.nix>`
      formatter = forAllSystems ({ pkgs }: pkgs.nixfmt);

      # nix run|build <flake-ref>#<pkg-name>
      # -- 
      # $ nix run <flake-ref>#hello
      apps = forAllSystems ({ pkgs }: {
        pydoc = {
          type = "app";
          program = "${pkgs.python311}/bin/pydoc3";


Struggling to figure out what the program path should be? Add a development shell to your flake, add the package to the environment, enter it and type type <program-name>. The output will be of the form /nix/store/<hash>-<package-name>/path/to/bin. The program path becomes ${pkgs.<package-name>}/path/to/bin.