#16484·nix

Preview and organize changes before downloading

Author: kelian-4Created Sep 18, 2026Updated Sep 18, 2026
Labelsfeature

Is your feature request related to a problem?

Nix commands can sometimes start downloading a large amount of data without giving the user a clear, structured overview of what is about to be downloaded.

For example, an operation may require several gigabytes of downloads, while the information displayed in the terminal can be difficult to read and understand before the downloads actually begin.

It would be useful to have a clearer overview of the operation beforehand, somewhat similar to the way pacman presents packages and download information before an installation or upgrade.

This is not limited to NixOS system updates. It could be useful for different Nix commands and workflows that involve fetching or building store paths, such as nix profile add, nix-shell, and others.

Proposed solution

The idea is to introduce a preview and organization step before downloading.

The workflow could look something like this:

Evaluation
    ↓
Preview
    ↓
Organization / review of changes
    ↓
Summary
    ↓
Confirmation
    ↓
Download / build
    ↓
Apply

The preview could provide a structured overview of:

  • which packages or derivations are involved;
  • how many items will be downloaded;
  • the total download size;
  • the total size after unpacking;
  • potentially, different categories of changes.

The main goal would be to give the user a clear view of what is going to happen before the download starts, making it easier to understand the operation and avoid unexpectedly downloading several gigabytes of data.

Alternative solutions

One possible alternative would be to keep the current command behavior and provide this workflow through an external wrapper around Nix commands.

I wrote a small Bash proof of concept to demonstrate what this could look like:

bash
#!/usr/bin/env bash

set -euo pipefail

TMPFILE=$(mktemp)
trap 'rm -f "$TMPFILE"' EXIT

sudo -v

(
while true; do
    sudo -n true
    sleep 60
    kill -0 "$$" 2>/dev/null || exit
done
) 2>/dev/null &
SUDO_KEEPALIVE_PID=$!

trap 'rm -f "$TMPFILE"; kill "$SUDO_KEEPALIVE_PID" 2>/dev/null' EXIT

###############################################################################
# Language
###############################################################################

LANG_CODE="${LC_MESSAGES:-${LANG:-en}}"

if [[ "$LANG_CODE" == fr* ]]; then
    TXT_SYNC="Synchronisation des channels..."
    TXT_EVAL="Évaluation de la configuration..."
    TXT_PACKAGES="Paquets"
    TXT_SUMMARY="Résumé"
    TXT_DOWNLOAD="Taille totale du téléchargement"
    TXT_UNPACKED="Taille totale décompressée"
    TXT_CONFIRM="Appliquer ces modifications ? [O/n] "
    TXT_REBUILD="Reconstruction du système..."
    TXT_CANCEL="Annulé."
    TXT_UPTODATE="Le système est déjà à jour."
    DEFAULT_REPLY="O"
else
    TXT_SYNC="Synchronizing channels..."
    TXT_EVAL="Evaluating configuration..."
    TXT_PACKAGES="Packages"
    TXT_SUMMARY="Summary"
    TXT_DOWNLOAD="Total download size"
    TXT_UNPACKED="Total unpacked size"
    TXT_CONFIRM="Apply these changes? [Y/n] "
    TXT_REBUILD="Rebuilding system..."
    TXT_CANCEL="Cancelled."
    TXT_UPTODATE="System is already up to date."
    DEFAULT_REPLY="Y"
fi

###############################################################################
# Arguments
###############################################################################

UPDATE=0
ARGS=()

for arg in "$@"; do
    if [[ "$arg" == "--update" ]]; then
        UPDATE=1
    else
        ARGS+=("$arg")
    fi
done

###############################################################################
# Update channels
###############################################################################

if (( UPDATE )); then
    echo ":: $TXT_SYNC"
    sudo nix-channel --update
fi

###############################################################################
# Dry build
###############################################################################

echo ":: $TXT_EVAL"

if ! sudo nixos-rebuild dry-build "${ARGS[@]}" >"$TMPFILE" 2>&1; then
    cat "$TMPFILE"
    exit 1
fi

###############################################################################
# Packages
###############################################################################

PACKAGES=$(
grep -oE '/nix/store/[^ ]+\.drv' "$TMPFILE" |
sed -E 's#.*/[a-z0-9]{32}-##; s/\.drv$//' |
awk '!seen[$0]++'
)

FETCH_LINE=$(grep "will be fetched" "$TMPFILE" || true)

if [[ -z "$PACKAGES" && -z "$FETCH_LINE" ]]; then
    echo "$TXT_UPTODATE"
    exit 0
fi

PACKAGE_COUNT=$(printf '%s\n' "$PACKAGES" | grep -c .)

echo ":: $TXT_PACKAGES ($PACKAGE_COUNT)"
echo

if command -v column >/dev/null 2>&1; then
    printf '%s\n' "$PACKAGES" | column
else
    printf '%s\n' "$PACKAGES"
fi

###############################################################################
# Summary
###############################################################################

echo
echo ":: $TXT_SUMMARY"
echo

if [[ -n "$FETCH_LINE" ]]; then
    DOWNLOAD_SIZE=$(echo "$FETCH_LINE" | sed -E 's/.*\(([0-9.]+ [A-Za-z]+) download,.*/\1/')
    UNPACKED_SIZE=$(echo "$FETCH_LINE" | sed -E 's/.*, ([0-9.]+ [A-Za-z]+) unpacked.*/\1/')

    printf "  %-32s %s\n" "$TXT_DOWNLOAD:" "$DOWNLOAD_SIZE"
    printf "  %-32s %s\n" "$TXT_UNPACKED:" "$UNPACKED_SIZE"
fi

###############################################################################
# Confirmation
###############################################################################

echo
read -rp "$TXT_CONFIRM" ANSWER
ANSWER=${ANSWER:-$DEFAULT_REPLY}

case "$ANSWER" in
    [oOyY]*)

        echo
        echo ":: $TXT_REBUILD"

        if command -v nh >/dev/null 2>&1; then
            if [[ "${NIXOS_CONFIG:-/etc/nixos/configuration.nix}" == "/etc/nixos/configuration.nix" ]]; then
                nh os switch -f '<nixpkgs/nixos>' "${ARGS[@]}"
            else
                nh os switch -f '<nixpkgs/nixos>' -- \
                    -I "nixos-config=${NIXOS_CONFIG}" \
                    "${ARGS[@]}"
            fi
        elif command -v nom >/dev/null 2>&1; then
            sudo nixos-rebuild switch "${ARGS[@]}" |& nom
        else
            sudo nixos-rebuild switch "${ARGS[@]}"
        fi
        ;;

    *)
        echo "$TXT_CANCEL"
        exit 0
        ;;

esac

Additional context

The script above is only intended as a proof of concept to illustrate the desired workflow and terminal presentation. It is not intended to prescribe a particular implementation.

The main idea is to make the information available from Nix more readable and actionable before the actual download begins.

Checklist


Add :+1: to [issues you find important](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc).